mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Merge pull request #6476 from kubkon/macho-exe
Link basic MachO executables with stage2
This commit is contained in:
commit
6aa668e020
@ -1257,3 +1257,47 @@ pub const reloc_type_x86_64 = packed enum(u4) {
|
||||
/// for thread local variables
|
||||
X86_64_RELOC_TLV,
|
||||
};
|
||||
|
||||
/// This symbol is a reference to an external non-lazy (data) symbol.
|
||||
pub const REFERENCE_FLAG_UNDEFINED_NON_LAZY: u16 = 0x0;
|
||||
|
||||
/// This symbol is a reference to an external lazy symbol—that is, to a function call.
|
||||
pub const REFERENCE_FLAG_UNDEFINED_LAZY: u16 = 0x1;
|
||||
|
||||
/// This symbol is defined in this module.
|
||||
pub const REFERENCE_FLAG_DEFINED: u16 = 0x2;
|
||||
|
||||
/// This symbol is defined in this module and is visible only to modules within this shared library.
|
||||
pub const REFERENCE_FLAG_PRIVATE_DEFINED: u16 = 3;
|
||||
|
||||
/// This symbol is defined in another module in this file, is a non-lazy (data) symbol, and is visible
|
||||
/// only to modules within this shared library.
|
||||
pub const REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY: u16 = 4;
|
||||
|
||||
/// This symbol is defined in another module in this file, is a lazy (function) symbol, and is visible
|
||||
/// only to modules within this shared library.
|
||||
pub const REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY: u16 = 5;
|
||||
|
||||
/// Must be set for any defined symbol that is referenced by dynamic-loader APIs (such as dlsym and
|
||||
/// NSLookupSymbolInImage) and not ordinary undefined symbol references. The strip tool uses this bit
|
||||
/// to avoid removing symbols that must exist: If the symbol has this bit set, strip does not strip it.
|
||||
pub const REFERENCED_DYNAMICALLY: u16 = 0x10;
|
||||
|
||||
/// Used by the dynamic linker at runtime. Do not set this bit.
|
||||
pub const N_DESC_DISCARDED: u16 = 0x20;
|
||||
|
||||
/// Indicates that this symbol is a weak reference. If the dynamic linker cannot find a definition
|
||||
/// for this symbol, it sets the address of this symbol to 0. The static linker sets this symbol given
|
||||
/// the appropriate weak-linking flags.
|
||||
pub const N_WEAK_REF: u16 = 0x40;
|
||||
|
||||
/// Indicates that this symbol is a weak definition. If the static linker or the dynamic linker finds
|
||||
/// another (non-weak) definition for this symbol, the weak definition is ignored. Only symbols in a
|
||||
/// coalesced section (page 23) can be marked as a weak definition.
|
||||
pub const N_WEAK_DEF: u16 = 0x80;
|
||||
|
||||
/// The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
|
||||
/// that the function is actually a resolver function and should
|
||||
/// be called to get the address of the real function to use.
|
||||
/// This bit is only available in .o files (MH_OBJECT filetype)
|
||||
pub const N_SYMBOL_RESOLVER: u16 = 0x100;
|
||||
|
||||
@ -1532,12 +1532,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
|
||||
const func = func_val.func;
|
||||
const got = &macho_file.sections.items[macho_file.got_section_index.?];
|
||||
const ptr_bytes = 8;
|
||||
const got_addr = @intCast(u32, got.addr + func.owner_decl.link.macho.offset_table_index.? * ptr_bytes);
|
||||
// ff 14 25 xx xx xx xx call [addr]
|
||||
try self.code.ensureCapacity(self.code.items.len + 7);
|
||||
self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });
|
||||
mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), got_addr);
|
||||
const got_addr = got.addr + func.owner_decl.link.macho.offset_table_index * @sizeOf(u64);
|
||||
// Here, we store the got address in %rax, and then call %rax
|
||||
// movabsq [addr], %rax
|
||||
try self.genSetReg(inst.base.src, .rax, .{ .memory = got_addr });
|
||||
// callq *%rax
|
||||
try self.code.ensureCapacity(self.code.items.len + 2);
|
||||
self.code.appendSliceAssumeCapacity(&[2]u8{ 0xff, 0xd0 });
|
||||
} else {
|
||||
return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
@ -2590,7 +2591,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const decl = payload.decl;
|
||||
const got = &macho_file.sections.items[macho_file.got_section_index.?];
|
||||
const got_addr = got.addr + decl.link.macho.offset_table_index.? * ptr_bytes;
|
||||
const got_addr = got.addr + decl.link.macho.offset_table_index * ptr_bytes;
|
||||
return MCValue{ .memory = got_addr };
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const decl = payload.decl;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -151,6 +151,45 @@ pub fn addCases(ctx: *TestContext) !void {
|
||||
{
|
||||
var case = ctx.exe("hello world", macosx_x64);
|
||||
case.addError("", &[_][]const u8{":1:1: error: no entry point found"});
|
||||
|
||||
// Incorrect return type
|
||||
case.addError(
|
||||
\\export fn _start() noreturn {
|
||||
\\}
|
||||
, &[_][]const u8{":2:1: error: expected noreturn, found void"});
|
||||
|
||||
// Regular old hello world
|
||||
case.addCompareOutput(
|
||||
\\export fn _start() noreturn {
|
||||
\\ print();
|
||||
\\
|
||||
\\ exit();
|
||||
\\}
|
||||
\\
|
||||
\\fn print() void {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
\\ : [number] "{rax}" (0x2000004),
|
||||
\\ [arg1] "{rdi}" (1),
|
||||
\\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
|
||||
\\ [arg3] "{rdx}" (14)
|
||||
\\ : "memory"
|
||||
\\ );
|
||||
\\ return;
|
||||
\\}
|
||||
\\
|
||||
\\fn exit() noreturn {
|
||||
\\ asm volatile ("syscall"
|
||||
\\ :
|
||||
\\ : [number] "{rax}" (0x2000001),
|
||||
\\ [arg1] "{rdi}" (0)
|
||||
\\ : "memory"
|
||||
\\ );
|
||||
\\ unreachable;
|
||||
\\}
|
||||
,
|
||||
"Hello, World!\n",
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user