Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 6c8ae06

Browse files
authored
Merge pull request #3059 from Geod24/osx-bindings
Add `core.sys.darwin.mach.{nlist,stab}` bindings merged-on-behalf-of: Nicholas Wilson <thewilsonator@users.noreply.github.com>
2 parents 9a0a431 + 83814a3 commit 6c8ae06

File tree

6 files changed

+418
-0
lines changed

6 files changed

+418
-0
lines changed

changelog/darwin_bindings.dd

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Added module `core.sys.darwin.mach.nlist` and `core.sys.darwin.mach.stab`
2+
3+
Those modules contains bindings for the 64 bits part of Mac OSX's
4+
`<mach-o/nlish.h>` and `<mach-o/stab.h>`, respectively,
5+
and can be used by users wishing to inspect binary data of Mach-O object files.

mak/COPY

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,10 @@ COPY=\
108108
$(IMPDIR)\core\sys\darwin\mach\getsect.d \
109109
$(IMPDIR)\core\sys\darwin\mach\kern_return.d \
110110
$(IMPDIR)\core\sys\darwin\mach\loader.d \
111+
$(IMPDIR)\core\sys\darwin\mach\nlist.d \
111112
$(IMPDIR)\core\sys\darwin\mach\port.d \
112113
$(IMPDIR)\core\sys\darwin\mach\semaphore.d \
114+
$(IMPDIR)\core\sys\darwin\mach\stab.d \
113115
$(IMPDIR)\core\sys\darwin\mach\thread_act.d \
114116
\
115117
$(IMPDIR)\core\sys\darwin\netinet\in_.d \

mak/DOCS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ DOCS=\
7070
$(DOCDIR)\core_sys_darwin_mach_getsect.html \
7171
$(DOCDIR)\core_sys_darwin_mach_kern_return.html \
7272
$(DOCDIR)\core_sys_darwin_mach_loader.html \
73+
$(DOCDIR)\core_sys_darwin_mach_nlist.html \
7374
$(DOCDIR)\core_sys_darwin_mach_port.html \
7475
$(DOCDIR)\core_sys_darwin_mach_semaphore.html \
76+
$(DOCDIR)\core_sys_darwin_mach_stab.html \
7577
$(DOCDIR)\core_sys_darwin_mach_thread_act.html \
7678
$(DOCDIR)\core_sys_darwin_netinet_in_.html \
7779
\

mak/SRCS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,10 @@ SRCS=\
113113
src\core\sys\darwin\mach\getsect.d \
114114
src\core\sys\darwin\mach\kern_return.d \
115115
src\core\sys\darwin\mach\loader.d \
116+
src\core\sys\darwin\mach\nlist.d \
116117
src\core\sys\darwin\mach\port.d \
117118
src\core\sys\darwin\mach\semaphore.d \
119+
src\core\sys\darwin\mach\stab.d \
118120
src\core\sys\darwin\mach\thread_act.d \
119121
src\core\sys\darwin\netinet\in_.d \
120122
\

src/core/sys/darwin/mach/nlist.d

Lines changed: 317 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
/**
2+
* Bindings for symbols and defines in `mach-o/nlist.h`
3+
*
4+
* This file was created based on the MacOSX 10.15 SDK.
5+
*
6+
* Copyright:
7+
* D Language Foundation 2020
8+
* Some documentation was extracted from the C headers
9+
* and is the property of Apple Inc.
10+
*
11+
* License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
12+
* Authors: Mathias 'Geod24' Lang
13+
* Source: $(DRUNTIMESRC core/sys/darwin/mach/_nlist.d)
14+
*/
15+
module core.sys.darwin.mach.nlist;
16+
17+
import core.stdc.config;
18+
19+
extern(C):
20+
nothrow:
21+
@nogc:
22+
pure:
23+
24+
/**
25+
* An entry in a list of symbols for 64-bits architectures
26+
*
27+
* Said symbols can be used to describe many different type of data,
28+
* including STABS debug infos. Introduced in MacOSX 10.8 SDK.
29+
*
30+
* See_Also:
31+
* https://developer.apple.com/documentation/kernel/nlist_64
32+
*/
33+
struct nlist_64
34+
{
35+
/// Compatibility alias, as `n_strx` is in an union in C code
36+
alias n_un = n_strx;
37+
38+
/**
39+
* Index of this symbol's name into the string table
40+
*
41+
* All names are stored as NUL-terminated strings into the string table.
42+
* For historical reason, the very first entry into the string table is `0`,
43+
* hence all non-NULL names have an index > 0.
44+
*/
45+
uint n_strx;
46+
47+
/**
48+
* A bitfield that describes the type of this symbol
49+
*
50+
* In reality, this describes 4 fields:
51+
* - N_STAB (top 3 bits)
52+
* - N_PEXT (next 1 bit)
53+
* - N_TYPE (next 3 bits)
54+
* - N_EXT (last 1 bit)
55+
*
56+
* The enum values `N_STAB`, `N_PEXT`, `N_TYPE`, and `N_EXT` should be used
57+
* as masks to check which type this `nlist_64` actually is.
58+
*/
59+
ubyte n_type;
60+
/// Section number (note that `0` means `NO_SECT`)
61+
ubyte n_sect;
62+
/* see <mach-o/stab.h> */
63+
ushort n_desc;
64+
/* value of this symbol (or stab offset) */
65+
ulong n_value;
66+
// Note: `n_value` *is* `uint64_t`, not `c_ulong` !
67+
}
68+
69+
/// Mask to use with `nlist_64.n_type` to check what the entry describes
70+
enum
71+
{
72+
/**
73+
* If any of these bits set, a symbolic debugging entry
74+
*
75+
* Only symbolic debugging entries have some of the N_STAB bits set and if any
76+
* of these bits are set then it is a symbolic debugging entry (a stab). In
77+
* which case then the values of the n_type field (the entire field) are given
78+
* in <mach-o/stab.h>
79+
*/
80+
N_STAB = 0xe0,
81+
/// Private external symbol bit
82+
N_PEXT = 0x10,
83+
/// Mask for the type bits
84+
N_TYPE = 0x0e, /* mask for the type bits */
85+
/// External symbol bit, set for external symbols
86+
N_EXT = 0x01,
87+
}
88+
89+
/// Values for `NTypeMask.N_TYPE` bits of the `nlist_64.n_type` field.
90+
enum
91+
{
92+
/// Undefined (`n_sect == NO_SECT`)
93+
N_UNDF = 0x0,
94+
/// Absolute (`n_sect == NO_SECT`)
95+
N_ABS = 0x2,
96+
/// Defined in section number `nlist_64.n_sect`
97+
N_SECT = 0xe,
98+
/// Prebound undefined (defined in a dylib)
99+
N_PBUD = 0xc,
100+
/**
101+
* Indirect symbol
102+
*
103+
* If the type is `N_INDR` then the symbol is defined to be the same as
104+
* another symbol. In this case the `n_value` field is an index into
105+
* the string table of the other symbol's name. When the other symbol
106+
* is defined then they both take on the defined type and value.
107+
*/
108+
N_INDR = 0xa,
109+
}
110+
111+
/**
112+
* Symbol is not in any section
113+
*
114+
* If the type is N_SECT then the n_sect field contains an ordinal of the
115+
* section the symbol is defined in. The sections are numbered from 1 and
116+
* refer to sections in order they appear in the load commands for the file
117+
* they are in. This means the same ordinal may very well refer to different
118+
* sections in different files.
119+
*
120+
* The n_value field for all symbol table entries (including N_STAB's) gets
121+
* updated by the link editor based on the value of it's n_sect field and where
122+
* the section n_sect references gets relocated. If the value of the n_sect
123+
* field is NO_SECT then it's n_value field is not changed by the link editor.
124+
*/
125+
enum NO_SECT = 0;
126+
127+
/// Maximum number of sections: 1 thru 255 inclusive
128+
enum MAX_SECT = 255;
129+
130+
/**
131+
* Common symbols are represented by undefined (N_UNDF) external (N_EXT) types
132+
* who's values (n_value) are non-zero. In which case the value of the n_value
133+
* field is the size (in bytes) of the common symbol. The n_sect field is set
134+
* to NO_SECT. The alignment of a common symbol may be set as a power of 2
135+
* between 2^1 and 2^15 as part of the n_desc field using the macros below. If
136+
* the alignment is not set (a value of zero) then natural alignment based on
137+
* the size is used.
138+
*/
139+
extern(D) ubyte GET_COMM_ALIGN(uint n_desc) @safe
140+
{
141+
return (((n_desc) >> 8) & 0x0f);
142+
}
143+
144+
/// Ditto
145+
extern(D) ref ushort SET_COMM_ALIGN(return ref ushort n_desc, size_t wanted_align) @safe
146+
{
147+
return n_desc = (((n_desc) & 0xf0ff) | (((wanted_align) & 0x0f) << 8));
148+
}
149+
150+
/**
151+
* To support the lazy binding of undefined symbols in the dynamic link-editor,
152+
* the undefined symbols in the symbol table (the nlist structures) are marked
153+
* with the indication if the undefined reference is a lazy reference or
154+
* non-lazy reference. If both a non-lazy reference and a lazy reference is
155+
* made to the same symbol the non-lazy reference takes precedence. A reference
156+
* is lazy only when all references to that symbol are made through a symbol
157+
* pointer in a lazy symbol pointer section.
158+
*
159+
* The implementation of marking nlist structures in the symbol table for
160+
* undefined symbols will be to use some of the bits of the n_desc field as a
161+
* reference type. The mask REFERENCE_TYPE will be applied to the n_desc field
162+
* of an nlist structure for an undefined symbol to determine the type of
163+
* undefined reference (lazy or non-lazy).
164+
*
165+
* The constants for the REFERENCE FLAGS are propagated to the reference table
166+
* in a shared library file. In that case the constant for a defined symbol,
167+
* REFERENCE_FLAG_DEFINED, is also used.
168+
*/
169+
enum
170+
{
171+
/// Reference type bits of the n_desc field of undefined symbols
172+
REFERENCE_TYPE = 0x7,
173+
174+
/// types of references
175+
REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0,
176+
/// Ditto
177+
REFERENCE_FLAG_UNDEFINED_LAZY = 1,
178+
/// Ditto
179+
REFERENCE_FLAG_DEFINED = 2,
180+
/// Ditto
181+
REFERENCE_FLAG_PRIVATE_DEFINED = 3,
182+
/// Ditto
183+
REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4,
184+
/// Ditto
185+
REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5,
186+
187+
/**
188+
* To simplify stripping of objects that use are used with the dynamic link
189+
* editor, the static link editor marks the symbols defined an object that are
190+
* referenced by a dynamicly bound object (dynamic shared libraries, bundles).
191+
* With this marking strip knows not to strip these symbols.
192+
*/
193+
REFERENCED_DYNAMICALLY = 0x0010,
194+
}
195+
196+
/**
197+
* For images created by the static link editor with the -twolevel_namespace
198+
* option in effect the flags field of the mach header is marked with
199+
* MH_TWOLEVEL. And the binding of the undefined references of the image are
200+
* determined by the static link editor. Which library an undefined symbol is
201+
* bound to is recorded by the static linker in the high 8 bits of the n_desc
202+
* field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded
203+
* references the libraries listed in the Mach-O's LC_LOAD_DYLIB,
204+
* LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB, and
205+
* LC_LAZY_LOAD_DYLIB, etc. load commands in the order they appear in the
206+
* headers. The library ordinals start from 1.
207+
* For a dynamic library that is built as a two-level namespace image the
208+
* undefined references from module defined in another use the same nlist struct
209+
* an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For
210+
* defined symbols in all images they also must have the library ordinal set to
211+
* SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable
212+
* image for references from plugins that refer to the executable that loads
213+
* them.
214+
*
215+
* The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace
216+
* image that are looked up by the dynamic linker with flat namespace semantics.
217+
* This ordinal was added as a feature in Mac OS X 10.3 by reducing the
218+
* value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries
219+
* or binaries built with older tools to have 0xfe (254) dynamic libraries. In
220+
* this case the ordinal value 0xfe (254) must be treated as a library ordinal
221+
* for compatibility.
222+
*/
223+
ubyte GET_LIBRARY_ORDINAL(uint n_desc) @safe { return ((n_desc) >> 8) & 0xff; }
224+
/// Ditto
225+
ref ushort SET_LIBRARY_ORDINAL(return scope ref ushort n_desc, uint ordinal) @safe
226+
{
227+
return n_desc = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8));
228+
}
229+
230+
/// Ditto
231+
enum
232+
{
233+
SELF_LIBRARY_ORDINAL = 0x00,
234+
MAX_LIBRARY_ORDINAL = 0xfd,
235+
DYNAMIC_LOOKUP_ORDINAL = 0xfe,
236+
EXECUTABLE_ORDINAL = 0xff,
237+
}
238+
239+
/**
240+
* The bit 0x0020 of the n_desc field is used for two non-overlapping purposes
241+
* and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED.
242+
*/
243+
enum
244+
{
245+
/**
246+
* Symbol is not to be dead stripped
247+
*
248+
* The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a
249+
* relocatable .o file (MH_OBJECT filetype). And is used to indicate to the
250+
* static link editor it is never to dead strip the symbol.
251+
*/
252+
N_NO_DEAD_STRIP = 0x0020,
253+
254+
/**
255+
* Symbol is discarded
256+
*
257+
* The N_DESC_DISCARDED bit of the n_desc field never appears in linked image.
258+
* But is used in very rare cases by the dynamic link editor to mark an in
259+
* memory symbol as discared and longer used for linking.
260+
*/
261+
N_DESC_DISCARDED =0x0020,
262+
263+
/**
264+
* Symbol is weak referenced
265+
*
266+
* The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that
267+
* the undefined symbol is allowed to be missing and is to have the address of
268+
* zero when missing.
269+
*/
270+
N_WEAK_REF = 0x0040,
271+
272+
/**
273+
* Coalesed symbol is a weak definition
274+
*
275+
* The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic
276+
* linkers that the symbol definition is weak, allowing a non-weak symbol to
277+
* also be used which causes the weak definition to be discared. Currently this
278+
* is only supported for symbols in coalesed sections.
279+
*/
280+
N_WEAK_DEF = 0x0080,
281+
282+
/**
283+
* Reference to a weak symbol
284+
*
285+
* The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker
286+
* that the undefined symbol should be resolved using flat namespace searching.
287+
*/
288+
N_REF_TO_WEAK = 0x0080,
289+
290+
/**
291+
* Symbol is a Thumb function (ARM)
292+
*
293+
* The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is
294+
* a defintion of a Thumb function.
295+
*/
296+
N_ARM_THUMB_DEF = 0x0008,
297+
298+
/**
299+
* The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
300+
* that the function is actually a resolver function and should
301+
* be called to get the address of the real function to use.
302+
* This bit is only available in .o files (MH_OBJECT filetype)
303+
*/
304+
N_SYMBOL_RESOLVER = 0x0100,
305+
306+
/**
307+
* The N_ALT_ENTRY bit of the n_desc field indicates that the
308+
* symbol is pinned to the previous content.
309+
*/
310+
N_ALT_ENTRY = 0x0200,
311+
312+
/**
313+
* The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used
314+
* infrequently and the linker should order it towards the end of the section.
315+
*/
316+
N_COLD_FUNC = 0x0400,
317+
}

0 commit comments

Comments
 (0)