21
21
import ghidra .app .util .bin .format .FactoryBundledWithBinaryReader ;
22
22
import ghidra .app .util .bin .format .macho .MachConstants ;
23
23
import ghidra .program .model .data .*;
24
+ import ghidra .util .exception .AssertException ;
24
25
import ghidra .util .exception .DuplicateNameException ;
25
26
26
27
/**
29
30
* @see <a href="https://opensource.apple.com/source/xnu/xnu-4570.71.2/EXTERNAL_HEADERS/mach-o/nlist.h.auto.html">mach-o/nlist.h</a>
30
31
*/
31
32
public class NList implements StructConverter {
32
- private int n_strx ;
33
- private byte n_type ;
34
- private byte n_sect ;
35
- private short n_desc ;
36
- private long n_value ;
33
+ private int n_strx ;
34
+ private byte n_type ;
35
+ private byte n_sect ;
36
+ private short n_desc ;
37
+ private long n_value ;
37
38
38
39
private String string ;
39
40
private boolean is32bit ;
40
41
41
- public static NList createNList (FactoryBundledWithBinaryReader reader ,
42
- boolean is32bit , long stringTableOffset ) throws IOException {
43
- NList nList = (NList ) reader .getFactory ().create (NList .class );
44
- nList .initNList (reader , is32bit , stringTableOffset );
45
- return nList ;
46
- }
42
+ public static NList createNList (FactoryBundledWithBinaryReader reader , boolean is32bit )
43
+ throws IOException {
44
+ NList nList = (NList ) reader .getFactory ().create (NList .class );
45
+ nList .initNList (reader , is32bit );
46
+ return nList ;
47
+ }
47
48
48
- /**
49
- * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD.
50
- */
51
- public NList () {}
49
+ /**
50
+ * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD.
51
+ */
52
+ public NList () {
53
+ }
52
54
53
- private void initNList (FactoryBundledWithBinaryReader reader , boolean is32bit ,
54
- long stringTableOffset ) throws IOException {
55
+ private void initNList (FactoryBundledWithBinaryReader reader , boolean is32bit )
56
+ throws IOException {
55
57
this .is32bit = is32bit ;
56
58
57
- n_strx = reader .readNextInt ();
58
- n_type = reader .readNextByte ();
59
- n_sect = reader .readNextByte ();
60
- n_desc = reader .readNextShort ();
59
+ n_strx = reader .readNextInt ();
60
+ n_type = reader .readNextByte ();
61
+ n_sect = reader .readNextByte ();
62
+ n_desc = reader .readNextShort ();
61
63
if (is32bit ) {
62
64
n_value = reader .readNextInt () & 0xffffffffL ;
63
65
}
64
66
else {
65
67
n_value = reader .readNextLong ();
66
68
}
69
+ }
70
+
71
+ /**
72
+ * Initialize the string from the string table.
73
+ * <p>
74
+ * You MUST call this method after the NLIST element is created!
75
+ * <p>
76
+ * Reading a large NList table can cause a large performance issue if the strings
77
+ * are initialized as the NList entry is created. The string table indexes are
78
+ * scattered. Initializing the strings linearly from the string table is much
79
+ * faster.
80
+ *
81
+ * @param reader
82
+ * @param stringTableOffset offset of the string table
83
+ */
84
+ public void initString (FactoryBundledWithBinaryReader reader , long stringTableOffset ) {
67
85
try {
68
86
string = reader .readAsciiString (stringTableOffset + n_strx );
69
87
}
@@ -74,19 +92,19 @@ private void initNList(FactoryBundledWithBinaryReader reader, boolean is32bit,
74
92
75
93
@ Override
76
94
public DataType toDataType () throws DuplicateNameException , IOException {
77
- StructureDataType struct = new StructureDataType ("nlist" , 0 );
78
- struct .add (DWORD , "n_strx" , null );
79
- struct .add ( BYTE , "n_type" , null );
80
- struct .add ( BYTE , "n_sect" , null );
81
- struct .add ( WORD , "n_desc" , null );
82
- if (is32bit ) {
83
- struct .add (DWORD , "n_value" , null );
84
- }
85
- else {
86
- struct .add (QWORD , "n_value" , null );
87
- }
88
- struct .setCategoryPath (new CategoryPath (MachConstants .DATA_TYPE_CATEGORY ));
89
- return struct ;
95
+ StructureDataType struct = new StructureDataType ("nlist" , 0 );
96
+ struct .add (DWORD , "n_strx" , null );
97
+ struct .add (BYTE , "n_type" , null );
98
+ struct .add (BYTE , "n_sect" , null );
99
+ struct .add (WORD , "n_desc" , null );
100
+ if (is32bit ) {
101
+ struct .add (DWORD , "n_value" , null );
102
+ }
103
+ else {
104
+ struct .add (QWORD , "n_value" , null );
105
+ }
106
+ struct .setCategoryPath (new CategoryPath (MachConstants .DATA_TYPE_CATEGORY ));
107
+ return struct ;
90
108
}
91
109
92
110
/**
@@ -95,6 +113,9 @@ public DataType toDataType() throws DuplicateNameException, IOException {
95
113
* @return the symbol string
96
114
*/
97
115
public String getString () {
116
+ if (string == null ) {
117
+ throw new AssertException ("initString must be called first" );
118
+ }
98
119
return string ;
99
120
}
100
121
@@ -105,6 +126,7 @@ public String getString() {
105
126
public int getStringTableIndex () {
106
127
return n_strx ;
107
128
}
129
+
108
130
/**
109
131
* Returns the symbol type flag.
110
132
* @return the symbol type flag
@@ -114,34 +136,40 @@ public byte getType() {
114
136
}
115
137
116
138
public boolean isTypeUndefined () {
117
- return n_sect == NListConstants .NO_SECT &&
118
- (n_type & NListConstants .MASK_N_TYPE ) == NListConstants .TYPE_N_UNDF ;
139
+ return n_sect == NListConstants .NO_SECT &&
140
+ (n_type & NListConstants .MASK_N_TYPE ) == NListConstants .TYPE_N_UNDF ;
119
141
}
142
+
120
143
public boolean isTypeAbsolute () {
121
- return n_sect == NListConstants .NO_SECT &&
122
- (n_type & NListConstants .MASK_N_TYPE ) == NListConstants .TYPE_N_ABS ;
144
+ return n_sect == NListConstants .NO_SECT &&
145
+ (n_type & NListConstants .MASK_N_TYPE ) == NListConstants .TYPE_N_ABS ;
123
146
}
147
+
124
148
public boolean isTypePreboundUndefined () {
125
- return n_sect == NListConstants .NO_SECT &&
126
- (n_type & NListConstants .MASK_N_TYPE ) == NListConstants .TYPE_N_PBUD ;
149
+ return n_sect == NListConstants .NO_SECT &&
150
+ (n_type & NListConstants .MASK_N_TYPE ) == NListConstants .TYPE_N_PBUD ;
127
151
}
128
152
129
153
public boolean isSymbolicDebugging () {
130
154
return (n_type & NListConstants .MASK_N_STAB ) != 0 ;
131
155
}
156
+
132
157
public boolean isPrivateExternal () {
133
158
return (n_type & NListConstants .MASK_N_PEXT ) != 0 ;
134
159
}
160
+
135
161
public boolean isExternal () {
136
162
return (n_type & NListConstants .MASK_N_EXT ) != 0 ;
137
163
}
164
+
138
165
public boolean isLazyBind () {
139
- return ( n_desc & NListConstants .REFERENCE_TYPE ) != 0 ;
166
+ return (n_desc & NListConstants .REFERENCE_TYPE ) != 0 ;
140
167
}
141
168
142
169
public boolean isThumbSymbol () {
143
170
return (n_desc & NListConstants .DESC_N_ARM_THUMB_DEF ) != 0 ;
144
171
}
172
+
145
173
/**
146
174
* An integer specifying the number of the section that this
147
175
* symbol can be found in, or NO_SECT if
@@ -151,13 +179,15 @@ public boolean isThumbSymbol() {
151
179
public byte getSection () {
152
180
return n_sect ;
153
181
}
182
+
154
183
/**
155
184
* A 16-bit value providing additional information about this symbol.
156
185
* @return a 16-bit value providing additional information about this symbol
157
186
*/
158
187
public short getDescription () {
159
188
return n_desc ;
160
189
}
190
+
161
191
/**
162
192
* An integer that contains the value of this symbol.
163
193
* The format of this value is different for each type of symbol.
0 commit comments