Skip to content

Commit fe019f4

Browse files
committed
Add __packed__ enum attribute support
1 parent 2b71c51 commit fe019f4

File tree

3 files changed

+102
-8
lines changed

3 files changed

+102
-8
lines changed

Ghidra/Features/Base/src/main/javacc/ghidra/app/util/cparser/C/C.jj

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -517,11 +517,12 @@ public class CParser {
517517
}
518518

519519

520-
private DataType allocateEnumDT(Token t, Declaration underlyingTypeDecl, ArrayList<EnumMember> list) {
520+
private DataType allocateEnumDT(Token t, Declaration underlyingTypeDecl, ArrayList<EnumMember> list, boolean isPacked) {
521521
String enumName = (t != null ? t.image : ("enum_" + cnt++));
522522
int defaultSize = (dtMgr != null && dtMgr.getDataOrganization() != null ? dtMgr.getDataOrganization().getIntegerSize() : 4);
523-
int initialEnumSize = defaultSize; // Initialize with default size, must be 1, 2, 4, or 8.
524-
523+
int initialEnumSize = defaultSize;
524+
addNearParseMessage("Enum " + enumName + " is packed: " + isPacked);
525+
525526
if (underlyingTypeDecl != null) {
526527
DataType resolvedUnderlyingType = underlyingTypeDecl.getDataType();
527528
if (resolvedUnderlyingType == null) {
@@ -559,7 +560,7 @@ public class CParser {
559560

560561
int minLen = enumDT.getMinimumPossibleLength();
561562
int finalEnumLength;
562-
if (underlyingTypeDecl == null) {
563+
if (underlyingTypeDecl == null && isPacked) {
563564
finalEnumLength = minLen;
564565
} else {
565566
finalEnumLength = Math.max(minLen, initialEnumSize);
@@ -1230,7 +1231,7 @@ TOKEN :
12301231
|
12311232
<UNALIGNED : "__unaligned" >
12321233
|
1233-
<PACKED : "__packed" >
1234+
<PACKED : ("__packed" | "__packed__" | "packed") >
12341235
|
12351236
<ATTRIBUTE : "__attribute" (["_"])* >
12361237
|
@@ -1854,7 +1855,7 @@ Declaration TypeQualifier(Declaration dec) : {}
18541855
<RESTRICT> |
18551856
<EXTENSION> |
18561857
<STATIC> |
1857-
<PACKED> |
1858+
<PACKED> { dec.addQualifier(PACKED); } |
18581859
<UNALIGNED> |
18591860
( DeclSpec(dec) )
18601861
)
@@ -2276,6 +2277,7 @@ DataType EnumSpecifier() : {
22762277
ArrayList<EnumMember> list;
22772278
Declaration attributeDecl = new Declaration();
22782279
Declaration typeDecl = null;
2280+
boolean isPacked = false;
22792281
}
22802282
{
22812283
<ENUM>
@@ -2285,17 +2287,21 @@ DataType EnumSpecifier() : {
22852287
[ t= <IDENTIFIER> ]
22862288
[ ":" typeDecl= BuiltInTypeSpecifier(new Declaration()) ]
22872289
"{" list= EnumeratorList() "}"
2290+
[AttributeSpecList(attributeDecl)]
22882291
{
2289-
dt = allocateEnumDT(t, typeDecl, list);
2292+
isPacked = attributeDecl.getQualifiers().contains(PACKED);
2293+
dt = allocateEnumDT(t, typeDecl, list, isPacked);
22902294
}
22912295
|
22922296
t= <IDENTIFIER>
22932297
[ ":" typeDecl= BuiltInTypeSpecifier(new Declaration()) ]
2298+
[AttributeSpecList(attributeDecl)]
22942299
{
22952300
dt= getEnumDef(t.image);
22962301
// not defined yet, define an empty one
22972302
if (dt == null) {
2298-
dt = allocateEnumDT(t, typeDecl, null);
2303+
isPacked = attributeDecl.getQualifiers().contains(PACKED);
2304+
dt = allocateEnumDT(t, typeDecl, null, isPacked);
22992305
}
23002306
}
23012307
)

Ghidra/Features/Base/src/test/java/ghidra/app/util/cparser/CParserTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,50 @@ public void testHeaderParsing() throws Exception {
495495
dt = dtMgr.getDataType(new CategoryPath("/"), "_C23_enum_longlong");
496496
assertTrue(dt instanceof Enum);
497497
assertEquals("enum _C23_enum_longlong size not correct", 8, dt.getLength());
498+
499+
dt = dtMgr.getDataType(new CategoryPath("/"), "packed_enum_style_1");
500+
assertTrue(dt instanceof Enum);
501+
assertEquals("enum packed_enum_style_1 size not correct", 1, dt.getLength());
502+
503+
dt = dtMgr.getDataType(new CategoryPath("/"), "packed_enum_style_2");
504+
assertTrue(dt instanceof Enum);
505+
assertEquals("enum packed_enum_style_2 size not correct", 1, dt.getLength());
506+
507+
dt = dtMgr.getDataType(new CategoryPath("/"), "packed_enum_cpp_style_1");
508+
assertTrue(dt instanceof Enum);
509+
assertEquals("enum packed_enum_cpp_style_1 size not correct", 1, dt.getLength());
510+
511+
dt = dtMgr.getDataType(new CategoryPath("/"), "packed_enum_cpp_style_2");
512+
assertTrue(dt instanceof Enum);
513+
assertEquals("enum packed_enum_cpp_style_2 size not correct", 1, dt.getLength());
514+
515+
dt = dtMgr.getDataType(new CategoryPath("/"), "packed_enum_cpp_style_gnu");
516+
assertTrue(dt instanceof Enum);
517+
assertEquals("enum packed_enum_cpp_style_gnu size not correct", 1, dt.getLength());
518+
519+
dt = dtMgr.getDataType(new CategoryPath("/"), "non_packed_enum");
520+
assertTrue(dt instanceof Enum);
521+
assertEquals("enum non_packed_enum size not correct", 4, dt.getLength());
522+
523+
dt = dtMgr.getDataType(new CategoryPath("/"), "packed_negative_enum");
524+
assertTrue(dt instanceof Enum);
525+
assertEquals("enum packed_negative_enum size not correct", 1, dt.getLength());
526+
assertEquals("enum packed_negative_enum value not correct", -1,
527+
((Enum) dt).getValue("A"));
528+
assertEquals("enum packed_negative_enum value not correct", -2,
529+
((Enum) dt).getValue("B"));
530+
assertEquals("enum packed_negative_enum value not correct", -3,
531+
((Enum) dt).getValue("C"));
532+
533+
dt = dtMgr.getDataType(new CategoryPath("/"), "normal_negative_enum");
534+
assertTrue(dt instanceof Enum);
535+
assertEquals("enum normal_negative_enum size not correct", 4, dt.getLength());
536+
assertEquals("enum normal_negative_enum value not correct", -1,
537+
((Enum) dt).getValue("A"));
538+
assertEquals("enum normal_negative_enum value not correct", -2,
539+
((Enum) dt).getValue("B"));
540+
assertEquals("enum normal_negative_enum value not correct", -3,
541+
((Enum) dt).getValue("C"));
498542

499543
dt = dtMgr.getDataType(new CategoryPath("/functions"), "__checkint");
500544
assertTrue("not a function", dt instanceof FunctionDefinition);

Ghidra/Features/Base/src/test/resources/ghidra/app/util/cparser/CParserTest.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,50 @@ enum _C23_enum_longlong : long long
991991
C = 3
992992
};
993993

994+
/**
995+
** Packed enums
996+
**/
997+
enum packed_enum_style_1 {
998+
A = 1,
999+
B = 2,
1000+
C = 3
1001+
} __attribute__((__packed__));
1002+
enum __attribute__((__packed__)) packed_enum_style_2 {
1003+
A = 1,
1004+
B = 2,
1005+
C = 3
1006+
};
1007+
enum [[packed]] packed_enum_cpp_style_1 {
1008+
A = 1,
1009+
B = 2,
1010+
C = 3
1011+
};
1012+
enum packed_enum_cpp_style_2 {
1013+
A = 1,
1014+
B = 2,
1015+
C = 3
1016+
} [[packed]];
1017+
enum [[gnu::packed]] packed_enum_cpp_style_gnu {
1018+
A = 1,
1019+
B = 2,
1020+
C = 3
1021+
};
1022+
enum non_packed_enum {
1023+
D = 4,
1024+
E = 5,
1025+
F = 6
1026+
};
1027+
enum packed_negative_enum {
1028+
A = -1,
1029+
B = -2,
1030+
C = -3
1031+
} __attribute__((__packed__));
1032+
enum normal_negative_enum {
1033+
A = -1,
1034+
B = -2,
1035+
C = -3
1036+
};
1037+
9941038
/**
9951039
** Casting
9961040
**/

0 commit comments

Comments
 (0)