Skip to content

Instantly share code, notes, and snippets.

@leroycep
Last active May 21, 2025 04:22
Show Gist options
  • Save leroycep/e18893f1aa58aeffc1699b6fbda6734b to your computer and use it in GitHub Desktop.
Save leroycep/e18893f1aa58aeffc1699b6fbda6734b to your computer and use it in GitHub Desktop.
A script to set the symbols from zig's compiler_rt symbols to hidden to fix issues with dynamic libraries
zig build-exe ./hide_compiler_rt.zig
./hide_compiler_rt path/to/input_lib.so path/to/output_lib.so
pub fn main() !void {
var debug_allocator = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = debug_allocator.deinit();
const gpa = debug_allocator.allocator();
const input = std.mem.span(std.os.argv[1]);
const output = std.mem.span(std.os.argv[2]);
const input_contents = try std.fs.cwd().readFileAlloc(gpa, input, 50_000_000);
defer gpa.free(input_contents);
var fbs = std.io.fixedBufferStream(input_contents);
const elf_header = try std.elf.Header.read(&fbs);
std.log.debug("elf header = {}", .{elf_header});
const dynamic_table_header = (try getDynamicTable(elf_header, input_contents)) orelse {
std.debug.print("No dynamic table program header found.", .{});
std.process.exit(1);
};
const dynamic_table_values = (try getSymbolTable(elf_header, input_contents, dynamic_table_header)) orelse {
std.debug.print("No dynamic symbol table found.", .{});
std.process.exit(1);
};
var symbols_to_hide_map = std.StringArrayHashMapUnmanaged(void){};
defer symbols_to_hide_map.deinit(gpa);
try symbols_to_hide_map.ensureUnusedCapacity(gpa, compiler_rt_symbols.len);
for (compiler_rt_symbols) |symbol_name| {
std.log.debug("hiding symbol {s}", .{symbol_name});
symbols_to_hide_map.putAssumeCapacityNoClobber(symbol_name, {});
}
const string_table_file_slice = fileSliceFromVirtualAddress(elf_header, input_contents, dynamic_table_values.string_table_virtual_address, dynamic_table_values.string_table_size) orelse return error.ElfStringSectionNotFound;
const string_table: []const u8 = input_contents[string_table_file_slice.offset..][0..string_table_file_slice.size];
const output_bytes = try gpa.dupe(u8, input_contents);
defer gpa.free(output_bytes);
var symbol_bytes = input_contents[dynamic_table_values.symbol_table_offset..];
var i: u64 = 0;
while (i + @sizeOf(std.elf.Elf64_Sym) < symbol_bytes.len) : (i += @sizeOf(std.elf.Elf64_Sym)) {
const symbol = std.mem.bytesAsValue(std.elf.Elf64_Sym, symbol_bytes[i..][0..@sizeOf(std.elf.Elf64_Sym)]);
if (symbol.st_name > string_table.len) {
std.log.debug("symbol 0x{x} = {}", .{ symbol.st_name, symbol });
break;
}
const name = std.mem.span(@as([*:0]const u8, @ptrCast(string_table[symbol.st_name..].ptr)));
std.log.debug("symbol \"{}\" = {}", .{ std.zig.fmtEscapes(name), symbol });
if (symbols_to_hide_map.contains(name)) {
const out_symbol = std.mem.bytesAsValue(std.elf.Elf64_Sym, output_bytes[dynamic_table_values.symbol_table_offset..][i..][0..@sizeOf(std.elf.Elf64_Sym)]);
out_symbol.st_other = @intFromEnum(std.elf.STV.HIDDEN);
}
}
// TODO: write modified file to output
try std.fs.cwd().writeFile(.{
.sub_path = output,
.data = output_bytes,
});
}
const symbol_names_to_hide_array = [_][:0]const u8{
// compiler_rt/count0bits
"__clzsi2",
"__clzdi2",
"__clzti2",
"__ctzsi2",
"__ctzdi2",
"__ctzti2",
"__ffssi2",
"__ffsdi2",
"__ffsti2",
// compiler_rt/ceil
"__ceilh",
"ceilf",
"ceil",
"__ceilx",
"ceilf128",
"ceilq",
"ceill",
// compiler_rt/cos
"__cosh",
"cosf",
"cos",
"__cosx",
"cosf128",
"cosq",
"cosl",
// compiler_rt/sin
"__sinh",
"sinf",
"sin",
"__sinx",
"sinf128",
"sinq",
"sinl",
// compiler_rt/sincos
"__sincosh",
"sincosf",
"sincos",
"__sincosx",
"sincosf128",
"sincosq",
"sincosl",
// symbols that are loaded from zig's compiler_rt before the segfault happens
"__zig_probe_stack",
"memset",
"__ubsan_handle_add_overflow",
"__ubsan_handle_mul_overflow",
"__ubsan_handle_sub_overflow",
"__ubsan_handle_alignment_assumption",
"__ubsan_handle_divrem_overflow",
"__ubsan_handle_float_cast_overflow",
"__ubsan_handle_invalid_builtin",
"__ubsan_handle_load_invalid_value",
"__ubsan_handle_negate_overflow",
"__ubsan_handle_nonnull_arg",
"__ubsan_handle_nonnull_return_v1",
"__ubsan_handle_out_of_bounds",
"__ubsan_handle_pointer_overflow",
"__ubsan_handle_shift_out_of_bounds",
"__ubsan_handle_type_mismatch_v1",
"__ubsan_handle_vla_bound_not_positive",
"memcpy",
"__extenddftf2",
"__extendxftf2",
"__umodti3",
"__udivti3",
"__udivmoddi4",
"__extendhfsf2",
"__gnu_f2h_ieee",
"__fixhfti",
"__fixsfti",
"__fixdfti",
"__fixxfti",
"__fixunshfti",
"__fixunssfti",
"__fixunsdfti",
"__fixunsxfti",
"__floattihf",
"__floattisf",
"__floattidf",
"__floattixf",
"__floatuntihf",
"__floatuntisf",
"__floatuntidf",
"__floatuntixf",
"__cmphf2",
"__cmpsf2",
"__cmpdf2",
"__cmptf2",
"__cmpxf2",
"__gehf2",
"__gesf2",
"__gedf2",
"__gexf2",
"__getf2",
"__addtf3",
"__subtf3",
"__multf3",
"__divsf3",
"__divtf3",
"__eqtf2",
"__netf2",
// "__ceilx",
// "ceilq",
// "cosf",
};
const compiler_rt_symbols = [_][]const u8{
"__floatsixf",
"_alloca",
"___chkstk_ms",
"__chkstk",
"_chkstk",
"__zig_probe_stack",
"__aarch64_cas1_relax",
"__aarch64_swp1_relax",
"__aarch64_ldadd1_relax",
"__aarch64_ldclr1_relax",
"__aarch64_ldeor1_relax",
"__aarch64_ldset1_relax",
"__aarch64_cas1_acq",
"__aarch64_swp1_acq",
"__aarch64_ldadd1_acq",
"__aarch64_ldclr1_acq",
"__aarch64_ldeor1_acq",
"__aarch64_ldset1_acq",
"__aarch64_cas1_rel",
"__aarch64_swp1_rel",
"__aarch64_ldadd1_rel",
"__aarch64_ldclr1_rel",
"__aarch64_ldeor1_rel",
"__aarch64_ldset1_rel",
"__aarch64_cas1_acq_rel",
"__aarch64_swp1_acq_rel",
"__aarch64_ldadd1_acq_rel",
"__aarch64_ldclr1_acq_rel",
"__aarch64_ldeor1_acq_rel",
"__aarch64_ldset1_acq_rel",
"__aarch64_cas2_relax",
"__aarch64_swp2_relax",
"__aarch64_ldadd2_relax",
"__aarch64_ldclr2_relax",
"__aarch64_ldeor2_relax",
"__aarch64_ldset2_relax",
"__aarch64_cas2_acq",
"__aarch64_swp2_acq",
"__aarch64_ldadd2_acq",
"__aarch64_ldclr2_acq",
"__aarch64_ldeor2_acq",
"__aarch64_ldset2_acq",
"__aarch64_cas2_rel",
"__aarch64_swp2_rel",
"__aarch64_ldadd2_rel",
"__aarch64_ldclr2_rel",
"__aarch64_ldeor2_rel",
"__aarch64_ldset2_rel",
"__aarch64_cas2_acq_rel",
"__aarch64_swp2_acq_rel",
"__aarch64_ldadd2_acq_rel",
"__aarch64_ldclr2_acq_rel",
"__aarch64_ldeor2_acq_rel",
"__aarch64_ldset2_acq_rel",
"__aarch64_cas4_relax",
"__aarch64_swp4_relax",
"__aarch64_ldadd4_relax",
"__aarch64_ldclr4_relax",
"__aarch64_ldeor4_relax",
"__aarch64_ldset4_relax",
"__aarch64_cas4_acq",
"__aarch64_swp4_acq",
"__aarch64_ldadd4_acq",
"__aarch64_ldclr4_acq",
"__aarch64_ldeor4_acq",
"__aarch64_ldset4_acq",
"__aarch64_cas4_rel",
"__aarch64_swp4_rel",
"__aarch64_ldadd4_rel",
"__aarch64_ldclr4_rel",
"__aarch64_ldeor4_rel",
"__aarch64_ldset4_rel",
"__aarch64_cas4_acq_rel",
"__aarch64_swp4_acq_rel",
"__aarch64_ldadd4_acq_rel",
"__aarch64_ldclr4_acq_rel",
"__aarch64_ldeor4_acq_rel",
"__aarch64_ldset4_acq_rel",
"__aarch64_cas8_relax",
"__aarch64_swp8_relax",
"__aarch64_ldadd8_relax",
"__aarch64_ldclr8_relax",
"__aarch64_ldeor8_relax",
"__aarch64_ldset8_relax",
"__aarch64_cas8_acq",
"__aarch64_swp8_acq",
"__aarch64_ldadd8_acq",
"__aarch64_ldclr8_acq",
"__aarch64_ldeor8_acq",
"__aarch64_ldset8_acq",
"__aarch64_cas8_rel",
"__aarch64_swp8_rel",
"__aarch64_ldadd8_rel",
"__aarch64_ldclr8_rel",
"__aarch64_ldeor8_rel",
"__aarch64_ldset8_rel",
"__aarch64_cas8_acq_rel",
"__aarch64_swp8_acq_rel",
"__aarch64_ldadd8_acq_rel",
"__aarch64_ldclr8_acq_rel",
"__aarch64_ldeor8_acq_rel",
"__aarch64_ldset8_acq_rel",
"__aarch64_cas16_relax",
"__aarch64_cas16_acq",
"__aarch64_cas16_rel",
"__aarch64_cas16_acq_rel",
"__logh",
"logf",
"log",
"__logx",
"logf128",
"logq",
"logl",
"__divsc3",
"__subhf3",
"__exp2h",
"exp2f",
"exp2",
"__exp2x",
"exp2f128",
"exp2q",
"exp2l",
"__muldc3",
"__sinh",
"sinf",
"sin",
"__sinx",
"sinf128",
"sinq",
"sinl",
"__extendsfkf2",
"_Qp_stoq",
"__extendsftf2",
"__trunckfsf2",
"_Qp_qtos",
"__trunctfsf2",
"__extenddfkf2",
"_Qp_dtoq",
"__extenddftf2",
"__aeabi_d2iz",
"__fixdfsi",
"__ashlsi3",
"__ashrsi3",
"__lshrsi3",
"__ashlti3",
"__ashrti3",
"__lshrti3",
"__aeabi_llsl",
"__aeabi_lasr",
"__aeabi_llsr",
"__ashldi3",
"__ashrdi3",
"__lshrdi3",
"__mulkf3",
"_Qp_mul",
"__multf3",
"__fixkfdi",
"_Qp_qtox",
"__fixtfdi",
"__aeabi_dsub",
"__subdf3",
"__absvdi2",
"__aeabi_fsub",
"__subsf3",
"__floatunsihf",
"__eqkf2",
"__nekf2",
"__ltkf2",
"__lekf2",
"_Qp_cmp",
"_Qp_feq",
"_Qp_fne",
"_Qp_flt",
"_Qp_fle",
"_Qp_fgt",
"_Qp_fge",
"__eqtf2",
"__netf2",
"__letf2",
"__cmptf2",
"__lttf2",
"__divxf3",
"__aeabi_fcmpge",
"__aeabi_fcmpgt",
"__gesf2",
"__gtsf2",
"__subkf3",
"_Qp_sub",
"__subtf3",
"__negkf2",
"__negtf2",
"__aeabi_dcmpun",
"__unorddf2",
"__floatundihf",
"__unordhf2",
"__sqrth",
"sqrtf",
"sqrt",
"__sqrtx",
"sqrtf128",
"sqrtq",
"sqrtl",
"__aeabi_l2f",
"__floatdisf",
"\x01__allrem",
"\x01__aullrem",
"__aeabi_f2d",
"__extendsfdf2",
"__fixdfti",
"__fixkfsi",
"_Qp_qtoi",
"__fixtfsi",
"__tanh",
"tanf",
"tan",
"__tanx",
"tanf128",
"tanq",
"tanl",
"__fixunskfsi",
"_Qp_qtoui",
"__fixunstfsi",
"\x01__alldiv",
"\x01__aulldiv",
"__mulxf3",
"memmove",
"__gexf2",
"__gtxf2",
"__unordkf2",
"__unordtf2",
"__fixsfti",
"__mulhc3",
"__floatuntihf",
"__aeabi_fadd",
"__addsf3",
"__fixunsdfti",
"__aeabi_f2lz",
"__fixsfdi",
"__floatuntisf",
"__aeabi_dcmpeq",
"__aeabi_dcmplt",
"__aeabi_dcmple",
"__eqdf2",
"__nedf2",
"__ledf2",
"__cmpdf2",
"__ltdf2",
"__fixhfsi",
"__fixhfdi",
"__trunctfhf2",
"__aeabi_fdiv",
"__divsf3",
"bcmp",
"__unordxf2",
"__floattitf",
"__floattikf",
"__negxf2",
"__udivei4",
"__umodei4",
"__aeabi_d2f",
"__truncdfsf2",
"__aeabi_fmul",
"__mulsf3",
"__aeabi_i2d",
"__floatsidf",
"__aeabi_ul2d",
"__floatundidf",
"__aeabi_dneg",
"__negdf2",
"__addosi4",
"__addodi4",
"__addoti4",
"__roundh",
"roundf",
"round",
"__roundx",
"roundf128",
"roundq",
"roundl",
"__extenddfxf2",
"__floattidf",
"__udivti3",
"__floatdikf",
"_Qp_xtoq",
"__floatditf",
"memset",
"__memset",
"__aeabi_ui2f",
"__floatunsisf",
"__extendxftf2",
"__sincosh",
"sincosf",
"sincos",
"__sincosx",
"sincosf128",
"sincosq",
"sincosl",
"__paritysi2",
"__paritydi2",
"__parityti2",
"__fixunshfsi",
"__fixxfsi",
"__cmpsi2",
"__cmpdi2",
"__cmpti2",
"__ucmpsi2",
"__ucmpdi2",
"__ucmpti2",
"__gnu_f2h_ieee",
"__aeabi_f2h",
"__truncsfhf2",
"__fixunsxfsi",
"__powihf2",
"__powisf2",
"__powidf2",
"__powikf2",
"__powitf2",
"__powixf2",
"__divkf3",
"_Qp_div",
"__divtf3",
"__aeabi_i2f",
"__floatsisf",
"__aeabi_f2ulz",
"__fixunssfdi",
"__floatsihf",
"__eqhf2",
"__nehf2",
"__lehf2",
"__cmphf2",
"__lthf2",
"__addxf3",
"__mulhf3",
"__fixxfdi",
"__log10h",
"log10f",
"log10",
"__log10x",
"log10f128",
"log10q",
"log10l",
"__fixunshfdi",
"__aeabi_d2lz",
"__fixdfdi",
"__floattisf",
"__gehf2",
"__gthf2",
"__fixunshfti",
"__fminh",
"fminf",
"fmin",
"__fminx",
"fminf128",
"fminq",
"fminl",
"__truncxfdf2",
"__divxc3",
"__udivmodti4",
"__atomic_load",
"__atomic_store",
"__atomic_exchange",
"__atomic_compare_exchange",
"__atomic_fetch_add_1",
"__atomic_fetch_add_2",
"__atomic_fetch_add_4",
"__atomic_fetch_add_8",
"__atomic_fetch_add_16",
"__atomic_fetch_sub_1",
"__atomic_fetch_sub_2",
"__atomic_fetch_sub_4",
"__atomic_fetch_sub_8",
"__atomic_fetch_sub_16",
"__atomic_fetch_and_1",
"__atomic_fetch_and_2",
"__atomic_fetch_and_4",
"__atomic_fetch_and_8",
"__atomic_fetch_and_16",
"__atomic_fetch_or_1",
"__atomic_fetch_or_2",
"__atomic_fetch_or_4",
"__atomic_fetch_or_8",
"__atomic_fetch_or_16",
"__atomic_fetch_xor_1",
"__atomic_fetch_xor_2",
"__atomic_fetch_xor_4",
"__atomic_fetch_xor_8",
"__atomic_fetch_xor_16",
"__atomic_fetch_nand_1",
"__atomic_fetch_nand_2",
"__atomic_fetch_nand_4",
"__atomic_fetch_nand_8",
"__atomic_fetch_nand_16",
"__atomic_fetch_umax_1",
"__atomic_fetch_umax_2",
"__atomic_fetch_umax_4",
"__atomic_fetch_umax_8",
"__atomic_fetch_umax_16",
"__atomic_fetch_umin_1",
"__atomic_fetch_umin_2",
"__atomic_fetch_umin_4",
"__atomic_fetch_umin_8",
"__atomic_fetch_umin_16",
"__atomic_load_1",
"__atomic_load_2",
"__atomic_load_4",
"__atomic_load_8",
"__atomic_load_16",
"__atomic_store_1",
"__atomic_store_2",
"__atomic_store_4",
"__atomic_store_8",
"__atomic_store_16",
"__atomic_exchange_1",
"__atomic_exchange_2",
"__atomic_exchange_4",
"__atomic_exchange_8",
"__atomic_exchange_16",
"__atomic_compare_exchange_1",
"__atomic_compare_exchange_2",
"__atomic_compare_exchange_4",
"__atomic_compare_exchange_8",
"__atomic_compare_exchange_16",
"__fmaxh",
"fmaxf",
"fmax",
"__fmaxx",
"fmaxf128",
"fmaxq",
"fmaxl",
"__aeabi_fcmpeq",
"__aeabi_fcmplt",
"__aeabi_fcmple",
"__eqsf2",
"__nesf2",
"__lesf2",
"__cmpsf2",
"__ltsf2",
"__negvsi2",
"__negvdi2",
"__negvti2",
"__aeabi_d2ulz",
"__fixunsdfdi",
"__mulsi3",
"__aeabi_lmul",
"__muldi3",
"__multi3",
"__bswapsi2",
"__bswapdi2",
"__bswapti2",
"__divdc3",
"__aeabi_ul2f",
"__floatundisf",
"__log2h",
"log2f",
"log2",
"__log2x",
"log2f128",
"log2q",
"log2l",
"__fixxfti",
"__floattihf",
"__fixunssfti",
"__divhf3",
"__divhc3",
"__modti3",
"__fixunstfti",
"__fixunskfti",
"__fixunskfdi",
"_Qp_qtoux",
"__fixunstfdi",
"__addhf3",
"__mulkc3",
"__multc3",
"__fmodh",
"fmodf",
"fmod",
"__fmodx",
"fmodf128",
"fmodq",
"fmodl",
"__floatuntitf",
"__floatuntikf",
"__aeabi_unwind_cpp_pr0",
"__aeabi_unwind_cpp_pr1",
"__aeabi_unwind_cpp_pr2",
"__aeabi_ldivmod",
"__aeabi_uldivmod",
"__aeabi_idivmod",
"__aeabi_uidivmod",
"__aeabi_memcpy",
"__aeabi_memcpy4",
"__aeabi_memcpy8",
"__aeabi_memmove",
"__aeabi_memmove4",
"__aeabi_memmove8",
"__aeabi_memset",
"__aeabi_memset4",
"__aeabi_memset8",
"__aeabi_memclr",
"__aeabi_memclr4",
"__aeabi_memclr8",
"__aeabi_read_tp",
"__aeabi_frsub",
"__aeabi_drsub",
"__emutls_get_address",
"__extendsfxf2",
"__mulxc3",
"__floorh",
"floorf",
"floor",
"__floorx",
"floorf128",
"floorq",
"floorl",
"__floatuntidf",
"__ceilh",
"ceilf",
"ceil",
"__ceilx",
"ceilf128",
"ceilq",
"ceill",
"__subosi4",
"__subodi4",
"__suboti4",
"__mulosi4",
"__mulodi4",
"__muloti4",
"__gnu_h2f_ieee",
"__aeabi_h2f",
"__extendhfsf2",
"__umodti3",
"__addkf3",
"_Qp_add",
"__addtf3",
"__aeabi_d2h",
"__truncdfhf2",
"__cosh",
"cosf",
"cos",
"__cosx",
"cosf128",
"cosq",
"cosl",
"__truncxfhf2",
"__fixunsxfdi",
"__floatdihf",
"__floatundikf",
"_Qp_uxtoq",
"__floatunditf",
"__exph",
"expf",
"exp",
"__expx",
"expf128",
"expq",
"expl",
"__fixunsxfti",
"__clzsi2",
"__clzdi2",
"__clzti2",
"__ctzsi2",
"__ctzdi2",
"__ctzti2",
"__ffssi2",
"__ffsdi2",
"__ffsti2",
"__divti3",
"__aeabi_ddiv",
"__divdf3",
"__fmah",
"fmaf",
"fma",
"__fmax",
"fmaf128",
"fmaq",
"fmal",
"__fixhfti",
"__isPlatformVersionAtLeast",
"__aeabi_dmul",
"__muldf3",
"__eqxf2",
"__nexf2",
"__lexf2",
"__cmpxf2",
"__ltxf2",
"__fabsh",
"fabsf",
"fabs",
"__fabsx",
"fabsf128",
"fabsq",
"fabsl",
"__aeabi_f2uiz",
"__fixunssfsi",
"__clear_cache",
"memcpy",
"__absvti2",
"__aeabi_fneg",
"__negsf2",
"__aeabi_fcmpun",
"__unordsf2",
"__extendhfdf2",
"__floatsikf",
"_Qp_itoq",
"__floatsitf",
"__popcountsi2",
"__popcountdi2",
"__popcountti2",
"__gekf2",
"__gtkf2",
"__getf2",
"__gttf2",
"__floatdixf",
"__floatundixf",
"__extendhftf2",
"__trunctfxf2",
"__mulsc3",
"__aeabi_f2iz",
"__fixsfsi",
"__floatunsikf",
"_Qp_uitoq",
"__floatunsitf",
"__trunckfdf2",
"_Qp_qtod",
"__trunctfdf2",
"__absvsi2",
"__aeabi_l2d",
"__floatdidf",
"__aeabi_dcmpge",
"__aeabi_dcmpgt",
"__gedf2",
"__gtdf2",
"memcmp",
"__aeabi_d2uiz",
"__fixunsdfsi",
"__extendhfxf2",
"__truncxfsf2",
"__subxf3",
"__fixtfti",
"__fixkfti",
"__neghf2",
"__floattixf",
"__divmodti4",
"__udivmoddi4",
"__divmoddi4",
"__aeabi_idiv",
"__aeabi_uidiv",
"__divsi3",
"__udivsi3",
"__divdi3",
"__udivdi3",
"__modsi3",
"__moddi3",
"__umodsi3",
"__umoddi3",
"__divmodsi4",
"__udivmodsi4",
"__aeabi_ui2d",
"__floatunsidf",
"__trunch",
"truncf",
"trunc",
"__truncx",
"truncf128",
"truncq",
"truncl",
"__stack_chk_fail",
"__chk_fail",
"__stack_chk_guard",
"__strcpy_chk",
"__strncpy_chk",
"__strcat_chk",
"__strncat_chk",
"__memcpy_chk",
"__memmove_chk",
"__memset_chk",
"__aeabi_dadd",
"__adddf3",
"__floatunsixf",
"__floatuntixf",
"__negsi2",
"__negdi2",
"__negti2",
"__divkc3",
"__divtc3",
};
fn getDynamicTable(elf_header: std.elf.Header, elf_bytes: []const u8) !?Elf64_Phdr {
const program_headers_len = @as(u64, elf_header.phentsize) * elf_header.phoff;
var program_header_bytes = elf_bytes[elf_header.phoff..][0..program_headers_len];
var program_header_offset: u64 = 0;
while (program_header_offset < program_header_bytes.len) : (program_header_offset += elf_header.phentsize) {
if (elf_header.is_64) {
std.debug.assert(elf_header.endian == builtin.cpu.arch.endian());
const program_header = std.mem.bytesAsValue(Elf64_Phdr, program_header_bytes[program_header_offset..][0..@sizeOf(elf.Elf64_Phdr)]);
std.log.debug("program header = {}", .{program_header});
switch (program_header.type) {
.dynamic => return program_header.*,
else => {},
}
} else {
const program_header = std.mem.bytesAsValue(elf.Elf32_Phdr, program_header_bytes[program_header_offset..][0..@sizeOf(elf.Elf32_Phdr)]);
_ = program_header;
@panic("TODO: unimplemented");
}
}
return null;
}
const DynamicTableValues = struct {
string_table_virtual_address: u64,
string_table_size: u64,
symbol_table_offset: u64,
};
fn getSymbolTable(elf_header: std.elf.Header, elf_bytes: []const u8, dynamic_table: Elf64_Phdr) !?DynamicTableValues {
std.debug.assert(elf_header.endian == builtin.cpu.arch.endian());
std.debug.assert(elf_header.is_64);
const dynv = std.mem.bytesAsSlice(u64, elf_bytes[dynamic_table.p_offset..][0..dynamic_table.p_filesz]);
var string_table_virtual_address: ?u64 = null;
var strings_size_opt: ?u64 = null;
var symbol_table_offset_opt: ?u64 = null;
var i: usize = 0;
while (dynv[i] != 0) : (i += 2) {
const dt_type: DynamicTableType = @enumFromInt(dynv[i]);
const value = dynv[i + 1];
switch (dt_type) {
.null => break,
.strtab => string_table_virtual_address = value,
.strsz => strings_size_opt = value,
.symtab => symbol_table_offset_opt = value,
else => if (std.enums.tagName(DynamicTableType, dt_type)) |tag_name| {
std.log.debug("dt {s} (0x{x}) = {}", .{ tag_name, @intFromEnum(dt_type), value });
} else {
std.log.debug("dt unknown (0x{x}) = {}", .{ @intFromEnum(dt_type), value });
},
}
}
return .{
.string_table_virtual_address = string_table_virtual_address orelse return null,
.string_table_size = strings_size_opt orelse return null,
.symbol_table_offset = symbol_table_offset_opt orelse return null,
};
}
pub const Elf64_Phdr = extern struct {
type: Type,
p_flags: u32,
p_offset: std.elf.Elf64_Off,
p_vaddr: std.elf.Elf64_Addr,
p_paddr: std.elf.Elf64_Addr,
p_filesz: std.elf.Elf64_Xword,
p_memsz: std.elf.Elf64_Xword,
p_align: std.elf.Elf64_Xword,
pub const Type = enum(u32) {
/// Program header table entry unused
null = 0,
/// Loadable program segment
load = 1,
/// Dynamic linking information
dynamic = 2,
/// Program interpreter
interp = 3,
/// Auxiliary information
note = 4,
/// Reserved
shlib = 5,
/// Entry for header table itself
phdr = 6,
/// Thread-local storage segment
tls = 7,
/// Number of defined types
num = 8,
_,
/// Start of OS-specific
pub const loos = 0x60000000;
/// GCC .eh_frame_hdr segment
pub const gnu_eh_frame = 0x6474e550;
/// Indicates stack executability
pub const gnu_stack = 0x6474e551;
/// Read-only after relocation
pub const gnu_relro = 0x6474e552;
pub const losunw = 0x6ffffffa;
/// Sun specific segment
pub const sunwbss = 0x6ffffffa;
/// Stack segment
pub const sunwstack = 0x6ffffffb;
pub const hisunw = 0x6fffffff;
/// End of OS-specific
pub const hios = 0x6fffffff;
/// Start of processor-specific
pub const loproc = 0x70000000;
/// End of processor-specific
pub const hiproc = 0x7fffffff;
};
};
pub const DynamicTableType = enum(u32) {
null = 0,
needed = 1,
pltrelsz = 2,
pltgot = 3,
hash = 4,
strtab = 5,
symtab = 6,
rela = 7,
relasz = 8,
relaent = 9,
strsz = 10,
syment = 11,
init = 12,
fini = 13,
soname = 14,
rpath = 15,
symbolic = 16,
rel = 17,
relsz = 18,
relent = 19,
pltrel = 20,
debug = 21,
textrel = 22,
jmprel = 23,
bind_now = 24,
init_array = 25,
fini_array = 26,
init_arraysz = 27,
fini_arraysz = 28,
runpath = 29,
flags = 30,
preinit_array = 32,
preinit_arraysz = 33,
symtab_shndx = 34,
relrsz = 35,
relr = 36,
relrent = 37,
num = 38,
gnu_hash = 0x6ffffef5,
versym = 0x6ffffff0,
relacount = 0x6ffffff9,
relcount = 0x6ffffffa,
flags_1 = 0x6ffffffb,
verdef = 0x6ffffffc,
verdefnum = 0x6ffffffd,
verneed = 0x6ffffffe,
verneednum = 0x6fffffff,
_,
pub const encoding: @This() = @enumFromInt(32);
pub const loos = 0x6000000d;
pub const hios = 0x6ffff000;
pub const loproc = 0x70000000;
pub const hiproc = 0x7fffffff;
pub const procnum = DT_MIPS_NUM;
pub const DT_VALRNGLO = 0x6ffffd00;
pub const DT_GNU_PRELINKED = 0x6ffffdf5;
pub const DT_GNU_CONFLICTSZ = 0x6ffffdf6;
pub const DT_GNU_LIBLISTSZ = 0x6ffffdf7;
pub const DT_CHECKSUM = 0x6ffffdf8;
pub const DT_PLTPADSZ = 0x6ffffdf9;
pub const DT_MOVEENT = 0x6ffffdfa;
pub const DT_MOVESZ = 0x6ffffdfb;
pub const DT_FEATURE_1 = 0x6ffffdfc;
pub const DT_POSFLAG_1 = 0x6ffffdfd;
pub const DT_SYMINSZ = 0x6ffffdfe;
pub const DT_SYMINENT = 0x6ffffdff;
pub const DT_VALRNGHI = 0x6ffffdff;
pub const DT_VALNUM = 12;
pub const DT_ADDRRNGLO = 0x6ffffe00;
pub const DT_GNU_HASH = 0x6ffffef5;
pub const DT_TLSDESC_PLT = 0x6ffffef6;
pub const DT_TLSDESC_GOT = 0x6ffffef7;
pub const DT_GNU_CONFLICT = 0x6ffffef8;
pub const DT_GNU_LIBLIST = 0x6ffffef9;
pub const DT_CONFIG = 0x6ffffefa;
pub const DT_DEPAUDIT = 0x6ffffefb;
pub const DT_AUDIT = 0x6ffffefc;
pub const DT_PLTPAD = 0x6ffffefd;
pub const DT_MOVETAB = 0x6ffffefe;
pub const DT_SYMINFO = 0x6ffffeff;
pub const DT_ADDRRNGHI = 0x6ffffeff;
pub const DT_ADDRNUM = 11;
pub const DT_VERSIONTAGNUM = 16;
pub const DT_AUXILIARY = 0x7ffffffd;
pub const DT_FILTER = 0x7fffffff;
pub const DT_EXTRANUM = 3;
pub const DT_SPARC_REGISTER = 0x70000001;
pub const DT_SPARC_NUM = 2;
pub const DT_MIPS_RLD_VERSION = 0x70000001;
pub const DT_MIPS_TIME_STAMP = 0x70000002;
pub const DT_MIPS_ICHECKSUM = 0x70000003;
pub const DT_MIPS_IVERSION = 0x70000004;
pub const DT_MIPS_FLAGS = 0x70000005;
pub const DT_MIPS_BASE_ADDRESS = 0x70000006;
pub const DT_MIPS_MSYM = 0x70000007;
pub const DT_MIPS_CONFLICT = 0x70000008;
pub const DT_MIPS_LIBLIST = 0x70000009;
pub const DT_MIPS_LOCAL_GOTNO = 0x7000000a;
pub const DT_MIPS_CONFLICTNO = 0x7000000b;
pub const DT_MIPS_LIBLISTNO = 0x70000010;
pub const DT_MIPS_SYMTABNO = 0x70000011;
pub const DT_MIPS_UNREFEXTNO = 0x70000012;
pub const DT_MIPS_GOTSYM = 0x70000013;
pub const DT_MIPS_HIPAGENO = 0x70000014;
pub const DT_MIPS_RLD_MAP = 0x70000016;
pub const DT_MIPS_DELTA_CLASS = 0x70000017;
pub const DT_MIPS_DELTA_CLASS_NO = 0x70000018;
pub const DT_MIPS_DELTA_INSTANCE = 0x70000019;
pub const DT_MIPS_DELTA_INSTANCE_NO = 0x7000001a;
pub const DT_MIPS_DELTA_RELOC = 0x7000001b;
pub const DT_MIPS_DELTA_RELOC_NO = 0x7000001c;
pub const DT_MIPS_DELTA_SYM = 0x7000001d;
pub const DT_MIPS_DELTA_SYM_NO = 0x7000001e;
pub const DT_MIPS_DELTA_CLASSSYM = 0x70000020;
pub const DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021;
pub const DT_MIPS_CXX_FLAGS = 0x70000022;
pub const DT_MIPS_PIXIE_INIT = 0x70000023;
pub const DT_MIPS_SYMBOL_LIB = 0x70000024;
pub const DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025;
pub const DT_MIPS_LOCAL_GOTIDX = 0x70000026;
pub const DT_MIPS_HIDDEN_GOTIDX = 0x70000027;
pub const DT_MIPS_PROTECTED_GOTIDX = 0x70000028;
pub const DT_MIPS_OPTIONS = 0x70000029;
pub const DT_MIPS_INTERFACE = 0x7000002a;
pub const DT_MIPS_DYNSTR_ALIGN = 0x7000002b;
pub const DT_MIPS_INTERFACE_SIZE = 0x7000002c;
pub const DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002d;
pub const DT_MIPS_PERF_SUFFIX = 0x7000002e;
pub const DT_MIPS_COMPACT_SIZE = 0x7000002f;
pub const DT_MIPS_GP_VALUE = 0x70000030;
pub const DT_MIPS_AUX_DYNAMIC = 0x70000031;
pub const DT_MIPS_PLTGOT = 0x70000032;
pub const DT_MIPS_RWPLT = 0x70000034;
pub const DT_MIPS_RLD_MAP_REL = 0x70000035;
pub const DT_MIPS_NUM = 0x36;
pub const DT_ALPHA_PLTRO = (loproc + 0);
pub const DT_ALPHA_NUM = 1;
pub const DT_PPC_GOT = (loproc + 0);
pub const DT_PPC_OPT = (loproc + 1);
pub const DT_PPC_NUM = 2;
pub const DT_PPC64_GLINK = (loproc + 0);
pub const DT_PPC64_OPD = (loproc + 1);
pub const DT_PPC64_OPDSZ = (loproc + 2);
pub const DT_PPC64_OPT = (loproc + 3);
pub const DT_PPC64_NUM = 4;
pub const DT_IA_64_PLT_RESERVE = (loproc + 0);
pub const DT_IA_64_NUM = 1;
pub const DT_NIOS2_GP = 0x70000002;
};
const FileSlice = struct {
offset: u64,
size: u64,
};
fn fileSliceFromVirtualAddress(elf_header: std.elf.Header, elf_bytes: []const u8, virtual_address: u64, virtual_address_size: u64) ?FileSlice {
const program_headers_len = @as(u64, elf_header.phentsize) * elf_header.phoff;
var program_header_bytes = elf_bytes[elf_header.phoff..][0..program_headers_len];
var program_header_offset: u64 = 0;
while (program_header_offset < program_header_bytes.len) : (program_header_offset += elf_header.phentsize) {
if (elf_header.is_64) {
std.debug.assert(elf_header.endian == builtin.cpu.arch.endian());
const program_header = std.mem.bytesAsValue(Elf64_Phdr, program_header_bytes[program_header_offset..][0..@sizeOf(elf.Elf64_Phdr)]);
if (virtual_address > program_header.p_vaddr and virtual_address < program_header.p_vaddr + program_header.p_filesz) {
return .{
.offset = virtual_address - program_header.p_vaddr + program_header.p_offset,
.size = virtual_address_size,
};
}
} else {
const program_header = std.mem.bytesAsValue(elf.Elf32_Phdr, program_header_bytes[program_header_offset..][0..@sizeOf(elf.Elf32_Phdr)]);
_ = program_header;
@panic("TODO: unimplemented");
}
}
return null;
}
const elf = std.elf;
const mem = std.mem;
const posix = std.posix;
const builtin = @import("builtin");
const std = @import("std");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment