| ... | @@ -9,8 +9,13 @@ si: Symbol.Known, | ... | @@ -9,8 +9,13 @@ si: Symbol.Known, |
| 9 | symtab: std.ArrayList(Symbol), | 9 | symtab: std.ArrayList(Symbol), |
| 10 | shstrtab: StringTable, | 10 | shstrtab: StringTable, |
| 11 | strtab: StringTable, | 11 | strtab: StringTable, |
| 12 | dynsym: std.ArrayList(Symbol.Index), | 12 | dynsym: std.AutoArrayHashMapUnmanaged(Symbol.Index, void), |
| 13 | dynstr: StringTable, | 13 | dynstr: StringTable, |
| | 14 | got: struct { |
| | 15 | len: u32, |
| | 16 | tlsld: GotIndex, |
| | 17 | plt: std.AutoArrayHashMapUnmanaged(Symbol.Index, void), |
| | 18 | }, |
| 14 | needed: std.AutoArrayHashMapUnmanaged(u32, void), | 19 | needed: std.AutoArrayHashMapUnmanaged(u32, void), |
| 15 | inputs: std.ArrayList(struct { | 20 | inputs: std.ArrayList(struct { |
| 16 | path: std.Build.Cache.Path, | 21 | path: std.Build.Cache.Path, |
| ... | @@ -35,8 +40,6 @@ pending_uavs: std.AutoArrayHashMapUnmanaged(Node.UavMapIndex, struct { | ... | @@ -35,8 +40,6 @@ pending_uavs: std.AutoArrayHashMapUnmanaged(Node.UavMapIndex, struct { |
| 35 | src_loc: Zcu.LazySrcLoc, | 40 | src_loc: Zcu.LazySrcLoc, |
| 36 | }), | 41 | }), |
| 37 | relocs: std.ArrayList(Reloc), | 42 | relocs: std.ArrayList(Reloc), |
| 38 | /// This is hiding actual bugs with global symbols! Reconsider once they are implemented correctly. | | |
| 39 | entry_hack: Symbol.Index, | | |
| 40 | const_prog_node: std.Progress.Node, | 43 | const_prog_node: std.Progress.Node, |
| 41 | synth_prog_node: std.Progress.Node, | 44 | synth_prog_node: std.Progress.Node, |
| 42 | input_prog_node: std.Progress.Node, | 45 | input_prog_node: std.Progress.Node, |
| ... | @@ -156,6 +159,7 @@ pub const Node = union(enum) { | ... | @@ -156,6 +159,7 @@ pub const Node = union(enum) { |
| 156 | comptime phdr: MappedFile.Node.Index = @enumFromInt(4), | 159 | comptime phdr: MappedFile.Node.Index = @enumFromInt(4), |
| 157 | comptime text: MappedFile.Node.Index = @enumFromInt(5), | 160 | comptime text: MappedFile.Node.Index = @enumFromInt(5), |
| 158 | comptime data: MappedFile.Node.Index = @enumFromInt(6), | 161 | comptime data: MappedFile.Node.Index = @enumFromInt(6), |
| | 162 | comptime data_rel_ro: MappedFile.Node.Index = @enumFromInt(7), |
| 159 | tls: MappedFile.Node.Index, | 163 | tls: MappedFile.Node.Index, |
| 160 | }; | 164 | }; |
| 161 | | 165 | |
| ... | @@ -179,71 +183,12 @@ pub const Section = struct { | ... | @@ -179,71 +183,12 @@ pub const Section = struct { |
| 179 | pub fn unwrap(ri: RelIndex) ?u32 { | 183 | pub fn unwrap(ri: RelIndex) ?u32 { |
| 180 | return switch (ri) { | 184 | return switch (ri) { |
| 181 | .none => null, | 185 | .none => null, |
| 182 | else => @intFromEnum(ri) - 1, | 186 | _ => @intFromEnum(ri) - 1, |
| 183 | }; | 187 | }; |
| 184 | } | 188 | } |
| 185 | }; | 189 | }; |
| 186 | }; | 190 | }; |
| 187 | | 191 | |
| 188 | pub const StringTable = struct { | | |
| 189 | map: std.HashMapUnmanaged(u32, void, StringTable.Context, std.hash_map.default_max_load_percentage), | | |
| 190 | | | |
| 191 | const Context = struct { | | |
| 192 | slice: []const u8, | | |
| 193 | | | |
| 194 | pub fn eql(_: Context, lhs_key: u32, rhs_key: u32) bool { | | |
| 195 | return lhs_key == rhs_key; | | |
| 196 | } | | |
| 197 | | | |
| 198 | pub fn hash(ctx: Context, key: u32) u64 { | | |
| 199 | return std.hash_map.hashString(std.mem.sliceTo(ctx.slice[key..], 0)); | | |
| 200 | } | | |
| 201 | }; | | |
| 202 | | | |
| 203 | const Adapter = struct { | | |
| 204 | slice: []const u8, | | |
| 205 | | | |
| 206 | pub fn eql(adapter: Adapter, lhs_key: []const u8, rhs_key: u32) bool { | | |
| 207 | return std.mem.startsWith(u8, adapter.slice[rhs_key..], lhs_key) and | | |
| 208 | adapter.slice[rhs_key + lhs_key.len] == 0; | | |
| 209 | } | | |
| 210 | | | |
| 211 | pub fn hash(_: Adapter, key: []const u8) u64 { | | |
| 212 | assert(std.mem.indexOfScalar(u8, key, 0) == null); | | |
| 213 | return std.hash_map.hashString(key); | | |
| 214 | } | | |
| 215 | }; | | |
| 216 | | | |
| 217 | pub fn get(st: *StringTable, elf: *Elf, si: Symbol.Index, key: []const u8) !u32 { | | |
| 218 | const gpa = elf.base.comp.gpa; | | |
| 219 | const ni = si.node(elf); | | |
| 220 | const slice_const = ni.sliceConst(&elf.mf); | | |
| 221 | const gop = try st.map.getOrPutContextAdapted( | | |
| 222 | gpa, | | |
| 223 | key, | | |
| 224 | StringTable.Adapter{ .slice = slice_const }, | | |
| 225 | .{ .slice = slice_const }, | | |
| 226 | ); | | |
| 227 | if (gop.found_existing) return gop.key_ptr.*; | | |
| 228 | const old_size, const new_size = size: switch (elf.shdrPtr(si.shndx(elf))) { | | |
| 229 | inline else => |shdr| { | | |
| 230 | const old_size: u32 = @intCast(elf.targetLoad(&shdr.size)); | | |
| 231 | const new_size: u32 = @intCast(old_size + key.len + 1); | | |
| 232 | elf.targetStore(&shdr.size, new_size); | | |
| 233 | break :size .{ old_size, new_size }; | | |
| 234 | }, | | |
| 235 | }; | | |
| 236 | _, const node_size = ni.location(&elf.mf).resolve(&elf.mf); | | |
| 237 | if (new_size > node_size) | | |
| 238 | try ni.resize(&elf.mf, gpa, new_size +| new_size / MappedFile.growth_factor); | | |
| 239 | const slice = ni.slice(&elf.mf)[old_size..]; | | |
| 240 | @memcpy(slice[0..key.len], key); | | |
| 241 | slice[key.len] = 0; | | |
| 242 | gop.key_ptr.* = old_size; | | |
| 243 | return old_size; | | |
| 244 | } | | |
| 245 | }; | | |
| 246 | | | |
| 247 | pub const Symbol = struct { | 192 | pub const Symbol = struct { |
| 248 | ni: MappedFile.Node.Index, | 193 | ni: MappedFile.Node.Index, |
| 249 | /// Relocations contained within this symbol | 194 | /// Relocations contained within this symbol |
| ... | @@ -260,6 +205,11 @@ pub const Symbol = struct { | ... | @@ -260,6 +205,11 @@ pub const Symbol = struct { |
| 260 | rodata, | 205 | rodata, |
| 261 | text, | 206 | text, |
| 262 | data, | 207 | data, |
| | 208 | data_rel_ro, |
| | 209 | got, |
| | 210 | got_plt, |
| | 211 | plt, |
| | 212 | plt_sec, |
| 263 | _, | 213 | _, |
| 264 | | 214 | |
| 265 | pub fn get(si: Symbol.Index, elf: *Elf) *Symbol { | 215 | pub fn get(si: Symbol.Index, elf: *Elf) *Symbol { |
| ... | @@ -333,7 +283,8 @@ pub const Symbol = struct { | ... | @@ -333,7 +283,8 @@ pub const Symbol = struct { |
| 333 | shndx: Shndx = .UNDEF, | 283 | shndx: Shndx = .UNDEF, |
| 334 | }; | 284 | }; |
| 335 | pub fn init(si: Symbol.Index, elf: *Elf, opts: InitOptions) !void { | 285 | pub fn init(si: Symbol.Index, elf: *Elf, opts: InitOptions) !void { |
| 336 | const gpa = elf.base.comp.gpa; | 286 | const comp = elf.base.comp; |
| | 287 | const gpa = comp.gpa; |
| 337 | const target_endian = elf.targetEndian(); | 288 | const target_endian = elf.targetEndian(); |
| 338 | const name_strtab_entry = try elf.string(.strtab, opts.name); | 289 | const name_strtab_entry = try elf.string(.strtab, opts.name); |
| 339 | switch (elf.shdrPtr(elf.si.symtab.shndx(elf))) { | 290 | switch (elf.shdrPtr(elf.si.symtab.shndx(elf))) { |
| ... | @@ -373,15 +324,34 @@ pub const Symbol = struct { | ... | @@ -373,15 +324,34 @@ pub const Symbol = struct { |
| 373 | @intFromEnum(si) + 1, | 324 | @intFromEnum(si) + 1, |
| 374 | )), | 325 | )), |
| 375 | } | 326 | } |
| 376 | if (opts.bind == .LOCAL or elf.si.dynsym == .null) return; | 327 | |
| 377 | const dsi = elf.dynsym.items.len; | 328 | if (opts.bind == .LOCAL) return; |
| 378 | try elf.dynsym.append(gpa, si); | 329 | no_entry: { |
| | 330 | if (std.mem.eql(u8, opts.name, entry: switch (elf.options.entry) { |
| | 331 | .default => switch (comp.config.output_mode) { |
| | 332 | .Exe => continue :entry .enabled, |
| | 333 | .Lib, .Obj => continue :entry .disabled, |
| | 334 | }, |
| | 335 | .disabled => break :no_entry, |
| | 336 | .enabled => "_start", |
| | 337 | .named => |named| named, |
| | 338 | })) { |
| | 339 | elf.si.entry = si; |
| | 340 | switch (elf.ehdrPtr()) { |
| | 341 | inline else => |ehdr| elf.targetStore(&ehdr.entry, @intCast(opts.value)), |
| | 342 | } |
| | 343 | } |
| | 344 | } |
| | 345 | |
| | 346 | if (elf.si.dynsym == .null) return; |
| | 347 | const dsi = elf.dynsym.count(); |
| | 348 | try elf.dynsym.putNoClobber(gpa, si, {}); |
| 379 | const name_dynstr_entry = try elf.string(.dynstr, opts.name); | 349 | const name_dynstr_entry = try elf.string(.dynstr, opts.name); |
| 380 | switch (elf.shdrPtr(elf.si.dynsym.shndx(elf))) { | 350 | switch (elf.shdrPtr(elf.si.dynsym.shndx(elf))) { |
| 381 | inline else => |shdr| { | 351 | inline else => |shdr| { |
| 382 | const old_size = elf.targetLoad(&shdr.size); | 352 | const old_size = elf.targetLoad(&shdr.size); |
| 383 | const ent_size = elf.targetLoad(&shdr.entsize); | 353 | const ent_size = elf.targetLoad(&shdr.entsize); |
| 384 | const new_size = ent_size * elf.dynsym.items.len; | 354 | const new_size = ent_size * elf.dynsym.count(); |
| 385 | if (new_size > old_size) { | 355 | if (new_size > old_size) { |
| 386 | elf.targetStore(&shdr.size, @intCast(new_size)); | 356 | elf.targetStore(&shdr.size, @intCast(new_size)); |
| 387 | const dynsym_ni = elf.si.dynsym.node(elf); | 357 | const dynsym_ni = elf.si.dynsym.node(elf); |
| ... | @@ -409,13 +379,136 @@ pub const Symbol = struct { | ... | @@ -409,13 +379,136 @@ pub const Symbol = struct { |
| 409 | if (target_endian != native_endian) std.mem.byteSwapAllFields(Sym, dynsym); | 379 | if (target_endian != native_endian) std.mem.byteSwapAllFields(Sym, dynsym); |
| 410 | }, | 380 | }, |
| 411 | } | 381 | } |
| | 382 | |
| | 383 | if (opts.type != .FUNC or opts.shndx != .UNDEF) return; |
| | 384 | const plt_index: u32 = @intCast(elf.got.plt.count()); |
| | 385 | try elf.got.plt.putNoClobber(gpa, si, {}); |
| | 386 | switch (elf.ehdrField(.machine)) { |
| | 387 | else => |machine| @panic(@tagName(machine)), |
| | 388 | .X86_64 => { |
| | 389 | const plt_ni = elf.si.plt.node(elf); |
| | 390 | _, const plt_node_size = plt_ni.location(&elf.mf).resolve(&elf.mf); |
| | 391 | const plt_addr = plt_addr: switch (elf.shdrPtr(elf.si.plt.shndx(elf))) { |
| | 392 | inline else => |shdr| { |
| | 393 | const old_size = 16 * (1 + plt_index); |
| | 394 | const new_size = old_size + 16; |
| | 395 | elf.targetStore(&shdr.size, new_size); |
| | 396 | if (new_size > plt_node_size) try plt_ni.resize( |
| | 397 | &elf.mf, |
| | 398 | gpa, |
| | 399 | new_size +| new_size / MappedFile.growth_factor, |
| | 400 | ); |
| | 401 | const plt_slice = plt_ni.slice(&elf.mf)[old_size..new_size]; |
| | 402 | @memcpy(plt_slice, &[16]u8{ |
| | 403 | 0xf3, 0x0f, 0x1e, 0xfa, // endbr64 |
| | 404 | 0x68, 0x00, 0x00, 0x00, 0x00, // push $0x0 |
| | 405 | 0xe9, 0x00, 0x00, 0x00, 0x00, // jmp 0 |
| | 406 | 0x66, 0x90, // xchg %ax,%ax |
| | 407 | }); |
| | 408 | std.mem.writeInt(u32, plt_slice[5..][0..4], plt_index, target_endian); |
| | 409 | std.mem.writeInt( |
| | 410 | i32, |
| | 411 | plt_slice[10..][0..4], |
| | 412 | 2 - @as(i32, @intCast(new_size)), |
| | 413 | target_endian, |
| | 414 | ); |
| | 415 | break :plt_addr elf.targetLoad(&shdr.addr) + old_size; |
| | 416 | }, |
| | 417 | }; |
| | 418 | |
| | 419 | const got_plt_shndx = elf.si.got_plt.shndx(elf); |
| | 420 | const got_plt_ni = elf.si.got_plt.node(elf); |
| | 421 | _, const got_plt_node_size = got_plt_ni.location(&elf.mf).resolve(&elf.mf); |
| | 422 | const got_plt_addr = got_plt_addr: switch (elf.shdrPtr(got_plt_shndx)) { |
| | 423 | inline else => |shdr, class| { |
| | 424 | const Addr = class.ElfN().Addr; |
| | 425 | const addr_size = @sizeOf(Addr); |
| | 426 | const old_size = addr_size * (3 + plt_index); |
| | 427 | const new_size = old_size + addr_size; |
| | 428 | elf.targetStore(&shdr.size, new_size); |
| | 429 | if (new_size > got_plt_node_size) try got_plt_ni.resize( |
| | 430 | &elf.mf, |
| | 431 | gpa, |
| | 432 | new_size +| new_size / MappedFile.growth_factor, |
| | 433 | ); |
| | 434 | std.mem.writeInt( |
| | 435 | Addr, |
| | 436 | got_plt_ni.slice(&elf.mf)[old_size..][0..addr_size], |
| | 437 | @intCast(plt_addr), |
| | 438 | target_endian, |
| | 439 | ); |
| | 440 | break :got_plt_addr elf.targetLoad(&shdr.addr) + old_size; |
| | 441 | }, |
| | 442 | }; |
| | 443 | |
| | 444 | const plt_sec_ni = elf.si.plt_sec.node(elf); |
| | 445 | _, const plt_sec_node_size = plt_sec_ni.location(&elf.mf).resolve(&elf.mf); |
| | 446 | switch (elf.shdrPtr(elf.si.plt_sec.shndx(elf))) { |
| | 447 | inline else => |shdr| { |
| | 448 | const old_size = 16 * plt_index; |
| | 449 | const new_size = old_size + 16; |
| | 450 | elf.targetStore(&shdr.size, new_size); |
| | 451 | if (new_size > plt_sec_node_size) try plt_sec_ni.resize( |
| | 452 | &elf.mf, |
| | 453 | gpa, |
| | 454 | new_size +| new_size / MappedFile.growth_factor, |
| | 455 | ); |
| | 456 | const plt_sec_slice = plt_sec_ni.slice(&elf.mf)[old_size..new_size]; |
| | 457 | @memcpy(plt_sec_slice, &[16]u8{ |
| | 458 | 0xf3, 0x0f, 0x1e, 0xfa, // endbr64 |
| | 459 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *0x0(%rip) |
| | 460 | 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, // nopw 0x0(%rax,%rax,1) |
| | 461 | }); |
| | 462 | std.mem.writeInt( |
| | 463 | i32, |
| | 464 | plt_sec_slice[6..][0..4], |
| | 465 | @intCast(@as(i64, @bitCast( |
| | 466 | got_plt_addr -% (elf.targetLoad(&shdr.addr) + old_size + 10), |
| | 467 | ))), |
| | 468 | target_endian, |
| | 469 | ); |
| | 470 | }, |
| | 471 | } |
| | 472 | |
| | 473 | const rela_plt_si = got_plt_shndx.get(elf).rela_si; |
| | 474 | const rela_plt_ni = rela_plt_si.node(elf); |
| | 475 | _, const rela_plt_node_size = rela_plt_ni.location(&elf.mf).resolve(&elf.mf); |
| | 476 | switch (elf.shdrPtr(rela_plt_si.shndx(elf))) { |
| | 477 | inline else => |shdr, class| { |
| | 478 | const Rela = class.ElfN().Rela; |
| | 479 | const rela_size = elf.targetLoad(&shdr.entsize); |
| | 480 | const old_size = rela_size * plt_index; |
| | 481 | const new_size = old_size + rela_size; |
| | 482 | elf.targetStore(&shdr.size, new_size); |
| | 483 | if (new_size > rela_plt_node_size) try rela_plt_ni.resize( |
| | 484 | &elf.mf, |
| | 485 | gpa, |
| | 486 | new_size +| new_size / MappedFile.growth_factor, |
| | 487 | ); |
| | 488 | const rela: *Rela = @ptrCast(@alignCast( |
| | 489 | rela_plt_ni.slice(&elf.mf)[@intCast(old_size)..@intCast(new_size)], |
| | 490 | )); |
| | 491 | rela.* = .{ |
| | 492 | .offset = @intCast(got_plt_addr), |
| | 493 | .info = .{ |
| | 494 | .type = @intFromEnum(std.elf.R_X86_64.JUMP_SLOT), |
| | 495 | .sym = @intCast(dsi), |
| | 496 | }, |
| | 497 | .addend = 0, |
| | 498 | }; |
| | 499 | if (target_endian != native_endian) std.mem.byteSwapAllFields(Rela, rela); |
| | 500 | }, |
| | 501 | } |
| | 502 | try rela_plt_ni.resized(gpa, &elf.mf); |
| | 503 | }, |
| | 504 | } |
| 412 | } | 505 | } |
| 413 | | 506 | |
| 414 | pub fn flushMoved(si: Symbol.Index, elf: *Elf, value: u64) void { | 507 | pub fn flushMoved(si: Symbol.Index, elf: *Elf, value: u64) void { |
| 415 | switch (elf.symPtr(si)) { | 508 | switch (elf.symPtr(si)) { |
| 416 | inline else => |sym, class| { | 509 | inline else => |sym, class| { |
| 417 | elf.targetStore(&sym.value, @intCast(value)); | 510 | elf.targetStore(&sym.value, @intCast(value)); |
| 418 | if (si == elf.entry_hack) { | 511 | if (si == elf.si.entry) { |
| 419 | @branchHint(.unlikely); | 512 | @branchHint(.unlikely); |
| 420 | @field(elf.ehdrPtr(), @tagName(class)).entry = sym.value; | 513 | @field(elf.ehdrPtr(), @tagName(class)).entry = sym.value; |
| 421 | } | 514 | } |
| ... | @@ -464,10 +557,16 @@ pub const Symbol = struct { | ... | @@ -464,10 +557,16 @@ pub const Symbol = struct { |
| 464 | comptime rodata: Symbol.Index = .rodata, | 557 | comptime rodata: Symbol.Index = .rodata, |
| 465 | comptime text: Symbol.Index = .text, | 558 | comptime text: Symbol.Index = .text, |
| 466 | comptime data: Symbol.Index = .data, | 559 | comptime data: Symbol.Index = .data, |
| | 560 | comptime data_rel_ro: Symbol.Index = .data_rel_ro, |
| | 561 | comptime got: Symbol.Index = .got, |
| | 562 | comptime got_plt: Symbol.Index = .got_plt, |
| | 563 | comptime plt: Symbol.Index = .plt, |
| | 564 | comptime plt_sec: Symbol.Index = .plt_sec, |
| 467 | dynsym: Symbol.Index, | 565 | dynsym: Symbol.Index, |
| 468 | dynstr: Symbol.Index, | 566 | dynstr: Symbol.Index, |
| 469 | dynamic: Symbol.Index, | 567 | dynamic: Symbol.Index, |
| 470 | tdata: Symbol.Index, | 568 | tdata: Symbol.Index, |
| | 569 | entry: Symbol.Index, |
| 471 | }; | 570 | }; |
| 472 | | 571 | |
| 473 | comptime { | 572 | comptime { |
| ... | @@ -475,6 +574,83 @@ pub const Symbol = struct { | ... | @@ -475,6 +574,83 @@ pub const Symbol = struct { |
| 475 | } | 574 | } |
| 476 | }; | 575 | }; |
| 477 | | 576 | |
| | 577 | pub const StringTable = struct { |
| | 578 | map: std.HashMapUnmanaged(u32, void, StringTable.Context, std.hash_map.default_max_load_percentage), |
| | 579 | |
| | 580 | const Context = struct { |
| | 581 | slice: []const u8, |
| | 582 | |
| | 583 | pub fn eql(_: Context, lhs_key: u32, rhs_key: u32) bool { |
| | 584 | return lhs_key == rhs_key; |
| | 585 | } |
| | 586 | |
| | 587 | pub fn hash(ctx: Context, key: u32) u64 { |
| | 588 | return std.hash_map.hashString(std.mem.sliceTo(ctx.slice[key..], 0)); |
| | 589 | } |
| | 590 | }; |
| | 591 | |
| | 592 | const Adapter = struct { |
| | 593 | slice: []const u8, |
| | 594 | |
| | 595 | pub fn eql(adapter: Adapter, lhs_key: []const u8, rhs_key: u32) bool { |
| | 596 | return std.mem.startsWith(u8, adapter.slice[rhs_key..], lhs_key) and |
| | 597 | adapter.slice[rhs_key + lhs_key.len] == 0; |
| | 598 | } |
| | 599 | |
| | 600 | pub fn hash(_: Adapter, key: []const u8) u64 { |
| | 601 | assert(std.mem.indexOfScalar(u8, key, 0) == null); |
| | 602 | return std.hash_map.hashString(key); |
| | 603 | } |
| | 604 | }; |
| | 605 | |
| | 606 | pub fn get(st: *StringTable, elf: *Elf, si: Symbol.Index, key: []const u8) !u32 { |
| | 607 | const gpa = elf.base.comp.gpa; |
| | 608 | const ni = si.node(elf); |
| | 609 | const slice_const = ni.sliceConst(&elf.mf); |
| | 610 | const gop = try st.map.getOrPutContextAdapted( |
| | 611 | gpa, |
| | 612 | key, |
| | 613 | StringTable.Adapter{ .slice = slice_const }, |
| | 614 | .{ .slice = slice_const }, |
| | 615 | ); |
| | 616 | if (gop.found_existing) return gop.key_ptr.*; |
| | 617 | try ni.resized(gpa, &elf.mf); |
| | 618 | const old_size, const new_size = size: switch (elf.shdrPtr(si.shndx(elf))) { |
| | 619 | inline else => |shdr| { |
| | 620 | const old_size: u32 = @intCast(elf.targetLoad(&shdr.size)); |
| | 621 | const new_size: u32 = @intCast(old_size + key.len + 1); |
| | 622 | elf.targetStore(&shdr.size, new_size); |
| | 623 | break :size .{ old_size, new_size }; |
| | 624 | }, |
| | 625 | }; |
| | 626 | _, const node_size = ni.location(&elf.mf).resolve(&elf.mf); |
| | 627 | if (new_size > node_size) |
| | 628 | try ni.resize(&elf.mf, gpa, new_size +| new_size / MappedFile.growth_factor); |
| | 629 | const slice = ni.slice(&elf.mf)[old_size..]; |
| | 630 | @memcpy(slice[0..key.len], key); |
| | 631 | slice[key.len] = 0; |
| | 632 | gop.key_ptr.* = old_size; |
| | 633 | return old_size; |
| | 634 | } |
| | 635 | }; |
| | 636 | |
| | 637 | pub const GotIndex = enum(u32) { |
| | 638 | none = std.math.maxInt(u32), |
| | 639 | _, |
| | 640 | |
| | 641 | pub fn wrap(i: ?u32) GotIndex { |
| | 642 | const gi: GotIndex = @enumFromInt(i orelse return .none); |
| | 643 | assert(gi != .none); |
| | 644 | return gi; |
| | 645 | } |
| | 646 | pub fn unwrap(gi: GotIndex) ?u32 { |
| | 647 | return switch (gi) { |
| | 648 | _ => @intFromEnum(gi), |
| | 649 | .none => null, |
| | 650 | }; |
| | 651 | } |
| | 652 | }; |
| | 653 | |
| 478 | pub const Reloc = extern struct { | 654 | pub const Reloc = extern struct { |
| 479 | type: Reloc.Type, | 655 | type: Reloc.Type, |
| 480 | prev: Reloc.Index, | 656 | prev: Reloc.Index, |
| ... | @@ -500,7 +676,6 @@ pub const Reloc = extern struct { | ... | @@ -500,7 +676,6 @@ pub const Reloc = extern struct { |
| 500 | .X86_64 => .{ .X86_64 = .NONE }, | 676 | .X86_64 => .{ .X86_64 = .NONE }, |
| 501 | }; | 677 | }; |
| 502 | } | 678 | } |
| 503 | | | |
| 504 | pub fn absAddr(elf: *Elf) Reloc.Type { | 679 | pub fn absAddr(elf: *Elf) Reloc.Type { |
| 505 | return switch (elf.ehdrField(.machine)) { | 680 | return switch (elf.ehdrField(.machine)) { |
| 506 | else => unreachable, | 681 | else => unreachable, |
| ... | @@ -510,7 +685,6 @@ pub const Reloc = extern struct { | ... | @@ -510,7 +685,6 @@ pub const Reloc = extern struct { |
| 510 | .X86_64 => .{ .X86_64 = .@"64" }, | 685 | .X86_64 => .{ .X86_64 = .@"64" }, |
| 511 | }; | 686 | }; |
| 512 | } | 687 | } |
| 513 | | | |
| 514 | pub fn sizeAddr(elf: *Elf) Reloc.Type { | 688 | pub fn sizeAddr(elf: *Elf) Reloc.Type { |
| 515 | return switch (elf.ehdrField(.machine)) { | 689 | return switch (elf.ehdrField(.machine)) { |
| 516 | else => unreachable, | 690 | else => unreachable, |
| ... | @@ -528,7 +702,6 @@ pub const Reloc = extern struct { | ... | @@ -528,7 +702,6 @@ pub const Reloc = extern struct { |
| 528 | => |machine| @unionInit(Reloc.Type, @tagName(machine), @enumFromInt(int)), | 702 | => |machine| @unionInit(Reloc.Type, @tagName(machine), @enumFromInt(int)), |
| 529 | }; | 703 | }; |
| 530 | } | 704 | } |
| 531 | | | |
| 532 | pub fn unwrap(rt: Reloc.Type, elf: *Elf) u32 { | 705 | pub fn unwrap(rt: Reloc.Type, elf: *Elf) u32 { |
| 533 | return switch (elf.ehdrField(.machine)) { | 706 | return switch (elf.ehdrField(.machine)) { |
| 534 | else => unreachable, | 707 | else => unreachable, |
| ... | @@ -558,7 +731,7 @@ pub const Reloc = extern struct { | ... | @@ -558,7 +731,7 @@ pub const Reloc = extern struct { |
| 558 | else => |ni| if (ni.hasMoved(&elf.mf)) return, | 731 | else => |ni| if (ni.hasMoved(&elf.mf)) return, |
| 559 | } | 732 | } |
| 560 | switch (reloc.target.get(elf).ni) { | 733 | switch (reloc.target.get(elf).ni) { |
| 561 | .none => return, | 734 | .none => {}, |
| 562 | else => |ni| if (ni.hasMoved(&elf.mf)) return, | 735 | else => |ni| if (ni.hasMoved(&elf.mf)) return, |
| 563 | } | 736 | } |
| 564 | const loc_slice = loc_ni.slice(&elf.mf)[@intCast(reloc.offset)..]; | 737 | const loc_slice = loc_ni.slice(&elf.mf)[@intCast(reloc.offset)..]; |
| ... | @@ -568,7 +741,6 @@ pub const Reloc = extern struct { | ... | @@ -568,7 +741,6 @@ pub const Reloc = extern struct { |
| 568 | const loc_sym = &symtab[@intFromEnum(reloc.loc)]; | 741 | const loc_sym = &symtab[@intFromEnum(reloc.loc)]; |
| 569 | const loc_shndx = elf.targetLoad(&loc_sym.shndx); | 742 | const loc_shndx = elf.targetLoad(&loc_sym.shndx); |
| 570 | assert(loc_shndx != std.elf.SHN_UNDEF); | 743 | assert(loc_shndx != std.elf.SHN_UNDEF); |
| 571 | const loc_value = elf.targetLoad(&loc_sym.value) + reloc.offset; | | |
| 572 | const target_sym = &symtab[@intFromEnum(reloc.target)]; | 744 | const target_sym = &symtab[@intFromEnum(reloc.target)]; |
| 573 | const target_value = | 745 | const target_value = |
| 574 | elf.targetLoad(&target_sym.value) +% @as(u64, @bitCast(reloc.addend)); | 746 | elf.targetLoad(&target_sym.value) +% @as(u64, @bitCast(reloc.addend)); |
| ... | @@ -582,10 +754,28 @@ pub const Reloc = extern struct { | ... | @@ -582,10 +754,28 @@ pub const Reloc = extern struct { |
| 582 | target_value, | 754 | target_value, |
| 583 | target_endian, | 755 | target_endian, |
| 584 | ), | 756 | ), |
| 585 | .PC32, .PLT32 => std.mem.writeInt( | 757 | .PC32 => std.mem.writeInt( |
| | 758 | i32, |
| | 759 | loc_slice[0..4], |
| | 760 | @intCast(@as(i64, @bitCast(target_value -% |
| | 761 | (elf.targetLoad(&loc_sym.value) + reloc.offset)))), |
| | 762 | target_endian, |
| | 763 | ), |
| | 764 | .PLT32 => std.mem.writeInt( |
| 586 | i32, | 765 | i32, |
| 587 | loc_slice[0..4], | 766 | loc_slice[0..4], |
| 588 | @intCast(@as(i64, @bitCast(target_value -% loc_value))), | 767 | @intCast(@as(i64, @bitCast( |
| | 768 | if (elf.got.plt.getIndex(reloc.target)) |plt_index| |
| | 769 | elf.targetLoad(&@field( |
| | 770 | elf.shdrPtr(elf.si.plt_sec.shndx(elf)), |
| | 771 | @tagName(class), |
| | 772 | ).addr) +% 16 * plt_index +% |
| | 773 | @as(u64, @bitCast(reloc.addend)) -% |
| | 774 | (elf.targetLoad(&loc_sym.value) + reloc.offset) |
| | 775 | else |
| | 776 | target_value -% |
| | 777 | (elf.targetLoad(&loc_sym.value) + reloc.offset), |
| | 778 | ))), |
| 589 | target_endian, | 779 | target_endian, |
| 590 | ), | 780 | ), |
| 591 | .@"32" => std.mem.writeInt( | 781 | .@"32" => std.mem.writeInt( |
| ... | @@ -600,6 +790,23 @@ pub const Reloc = extern struct { | ... | @@ -600,6 +790,23 @@ pub const Reloc = extern struct { |
| 600 | @intCast(@as(i64, @bitCast(target_value))), | 790 | @intCast(@as(i64, @bitCast(target_value))), |
| 601 | target_endian, | 791 | target_endian, |
| 602 | ), | 792 | ), |
| | 793 | .TLSLD => std.mem.writeInt( |
| | 794 | i32, |
| | 795 | loc_slice[0..4], |
| | 796 | @intCast(@as(i64, @bitCast( |
| | 797 | elf.targetLoad(&symtab[@intFromEnum(elf.si.got)].value) +% |
| | 798 | @as(u64, @bitCast(reloc.addend)) +% |
| | 799 | @as(u64, 8) * elf.got.tlsld.unwrap().? -% |
| | 800 | (elf.targetLoad(&loc_sym.value) + reloc.offset), |
| | 801 | ))), |
| | 802 | target_endian, |
| | 803 | ), |
| | 804 | .DTPOFF32 => std.mem.writeInt( |
| | 805 | i32, |
| | 806 | loc_slice[0..4], |
| | 807 | @intCast(@as(i64, @bitCast(target_value))), |
| | 808 | target_endian, |
| | 809 | ), |
| 603 | .TPOFF32 => { | 810 | .TPOFF32 => { |
| 604 | const phdr = @field(elf.phdrSlice(), @tagName(class)); | 811 | const phdr = @field(elf.phdrSlice(), @tagName(class)); |
| 605 | const ph = &phdr[elf.getNode(elf.ni.tls).segment]; | 812 | const ph = &phdr[elf.getNode(elf.ni.tls).segment]; |
| ... | @@ -614,13 +821,15 @@ pub const Reloc = extern struct { | ... | @@ -614,13 +821,15 @@ pub const Reloc = extern struct { |
| 614 | .SIZE32 => std.mem.writeInt( | 821 | .SIZE32 => std.mem.writeInt( |
| 615 | u32, | 822 | u32, |
| 616 | loc_slice[0..4], | 823 | loc_slice[0..4], |
| 617 | @intCast(elf.targetLoad(&target_sym.size)), | 824 | @intCast( |
| | 825 | elf.targetLoad(&target_sym.size) +% @as(u64, @bitCast(reloc.addend)), |
| | 826 | ), |
| 618 | target_endian, | 827 | target_endian, |
| 619 | ), | 828 | ), |
| 620 | .SIZE64 => std.mem.writeInt( | 829 | .SIZE64 => std.mem.writeInt( |
| 621 | u64, | 830 | u64, |
| 622 | loc_slice[0..8], | 831 | loc_slice[0..8], |
| 623 | @intCast(elf.targetLoad(&target_sym.size)), | 832 | elf.targetLoad(&target_sym.size) +% @as(u64, @bitCast(reloc.addend)), |
| 624 | target_endian, | 833 | target_endian, |
| 625 | ), | 834 | ), |
| 626 | }, | 835 | }, |
| ... | @@ -711,7 +920,7 @@ fn create( | ... | @@ -711,7 +920,7 @@ fn create( |
| 711 | .big => .@"2MSB", | 920 | .big => .@"2MSB", |
| 712 | }; | 921 | }; |
| 713 | const osabi: std.elf.OSABI = switch (target.os.tag) { | 922 | const osabi: std.elf.OSABI = switch (target.os.tag) { |
| 714 | else => .NONE, | 923 | else => if (target.abi.isGnu()) .GNU else .NONE, |
| 715 | .freestanding, .other => .STANDALONE, | 924 | .freestanding, .other => .STANDALONE, |
| 716 | .netbsd => .NETBSD, | 925 | .netbsd => .NETBSD, |
| 717 | .illumos => .SOLARIS, | 926 | .illumos => .SOLARIS, |
| ... | @@ -776,6 +985,7 @@ fn create( | ... | @@ -776,6 +985,7 @@ fn create( |
| 776 | .dynstr = .null, | 985 | .dynstr = .null, |
| 777 | .dynamic = .null, | 986 | .dynamic = .null, |
| 778 | .tdata = .null, | 987 | .tdata = .null, |
| | 988 | .entry = .null, |
| 779 | }, | 989 | }, |
| 780 | .symtab = .empty, | 990 | .symtab = .empty, |
| 781 | .shstrtab = .{ | 991 | .shstrtab = .{ |
| ... | @@ -788,6 +998,11 @@ fn create( | ... | @@ -788,6 +998,11 @@ fn create( |
| 788 | .dynstr = .{ | 998 | .dynstr = .{ |
| 789 | .map = .empty, | 999 | .map = .empty, |
| 790 | }, | 1000 | }, |
| | 1001 | .got = .{ |
| | 1002 | .len = 0, |
| | 1003 | .tlsld = .none, |
| | 1004 | .plt = .empty, |
| | 1005 | }, |
| 791 | .needed = .empty, | 1006 | .needed = .empty, |
| 792 | .inputs = .empty, | 1007 | .inputs = .empty, |
| 793 | .input_sections = .empty, | 1008 | .input_sections = .empty, |
| ... | @@ -801,7 +1016,6 @@ fn create( | ... | @@ -801,7 +1016,6 @@ fn create( |
| 801 | }), | 1016 | }), |
| 802 | .pending_uavs = .empty, | 1017 | .pending_uavs = .empty, |
| 803 | .relocs = .empty, | 1018 | .relocs = .empty, |
| 804 | .entry_hack = .null, | | |
| 805 | .const_prog_node = .none, | 1019 | .const_prog_node = .none, |
| 806 | .synth_prog_node = .none, | 1020 | .synth_prog_node = .none, |
| 807 | .input_prog_node = .none, | 1021 | .input_prog_node = .none, |
| ... | @@ -823,6 +1037,7 @@ pub fn deinit(elf: *Elf) void { | ... | @@ -823,6 +1037,7 @@ pub fn deinit(elf: *Elf) void { |
| 823 | elf.strtab.map.deinit(gpa); | 1037 | elf.strtab.map.deinit(gpa); |
| 824 | elf.dynsym.deinit(gpa); | 1038 | elf.dynsym.deinit(gpa); |
| 825 | elf.dynstr.map.deinit(gpa); | 1039 | elf.dynstr.map.deinit(gpa); |
| | 1040 | elf.got.plt.deinit(gpa); |
| 826 | elf.needed.deinit(gpa); | 1041 | elf.needed.deinit(gpa); |
| 827 | for (elf.inputs.items) |input| if (input.member) |m| gpa.free(m); | 1042 | for (elf.inputs.items) |input| if (input.member) |m| gpa.free(m); |
| 828 | elf.inputs.deinit(gpa); | 1043 | elf.inputs.deinit(gpa); |
| ... | @@ -873,14 +1088,16 @@ fn initHeaders( | ... | @@ -873,14 +1088,16 @@ fn initHeaders( |
| 873 | phnum += 1; | 1088 | phnum += 1; |
| 874 | const data_phndx = phnum; | 1089 | const data_phndx = phnum; |
| 875 | phnum += 1; | 1090 | phnum += 1; |
| 876 | const dynamic_phndx = if (have_dynamic_section) phndx: { | 1091 | const tls_phndx = if (comp.config.any_non_single_threaded) phndx: { |
| 877 | defer phnum += 1; | 1092 | defer phnum += 1; |
| 878 | break :phndx phnum; | 1093 | break :phndx phnum; |
| 879 | } else undefined; | 1094 | } else undefined; |
| 880 | const tls_phndx = if (comp.config.any_non_single_threaded) phndx: { | 1095 | const dynamic_phndx = if (have_dynamic_section) phndx: { |
| 881 | defer phnum += 1; | 1096 | defer phnum += 1; |
| 882 | break :phndx phnum; | 1097 | break :phndx phnum; |
| 883 | } else undefined; | 1098 | } else undefined; |
| | 1099 | const relro_phndx = phnum; |
| | 1100 | phnum += 1; |
| 884 | | 1101 | |
| 885 | const expected_nodes_len = expected_nodes_len: switch (@"type") { | 1102 | const expected_nodes_len = expected_nodes_len: switch (@"type") { |
| 886 | .NONE, .CORE, _ => unreachable, | 1103 | .NONE, .CORE, _ => unreachable, |
| ... | @@ -888,12 +1105,14 @@ fn initHeaders( | ... | @@ -888,12 +1105,14 @@ fn initHeaders( |
| 888 | defer phnum = 0; | 1105 | defer phnum = 0; |
| 889 | break :expected_nodes_len 5 + phnum; | 1106 | break :expected_nodes_len 5 + phnum; |
| 890 | }, | 1107 | }, |
| 891 | .EXEC, .DYN => break :expected_nodes_len 5 + phnum * 2 + | 1108 | .EXEC, .DYN => break :expected_nodes_len 9 + phnum * 2 + |
| 892 | @as(usize, 2) * @intFromBool(have_dynamic_section), | 1109 | @as(usize, 4) * @intFromBool(have_dynamic_section), |
| 893 | }; | 1110 | }; |
| 894 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); | 1111 | try elf.nodes.ensureTotalCapacity(gpa, expected_nodes_len); |
| 895 | try elf.shdrs.ensureTotalCapacity(gpa, shnum); | 1112 | try elf.shdrs.ensureTotalCapacity(gpa, shnum); |
| 896 | try elf.phdrs.resize(gpa, phnum); | 1113 | try elf.phdrs.resize(gpa, phnum); |
| | 1114 | try elf.symtab.ensureTotalCapacity(gpa, 1); |
| | 1115 | if (have_dynamic_section) try elf.dynsym.ensureTotalCapacity(gpa, 1); |
| 897 | elf.nodes.appendAssumeCapacity(.file); | 1116 | elf.nodes.appendAssumeCapacity(.file); |
| 898 | | 1117 | |
| 899 | switch (class) { | 1118 | switch (class) { |
| ... | @@ -976,10 +1195,18 @@ fn initHeaders( | ... | @@ -976,10 +1195,18 @@ fn initHeaders( |
| 976 | elf.nodes.appendAssumeCapacity(.{ .segment = data_phndx }); | 1195 | elf.nodes.appendAssumeCapacity(.{ .segment = data_phndx }); |
| 977 | elf.phdrs.items[data_phndx] = elf.ni.data; | 1196 | elf.phdrs.items[data_phndx] = elf.ni.data; |
| 978 | | 1197 | |
| | 1198 | assert(elf.ni.data_rel_ro == try elf.mf.addOnlyChildNode(gpa, elf.ni.data, .{ |
| | 1199 | .alignment = elf.mf.flags.block_size, |
| | 1200 | .moved = true, |
| | 1201 | .bubbles_moved = false, |
| | 1202 | })); |
| | 1203 | elf.nodes.appendAssumeCapacity(.{ .segment = relro_phndx }); |
| | 1204 | elf.phdrs.items[relro_phndx] = elf.ni.data_rel_ro; |
| | 1205 | |
| 979 | break :ph_vaddr switch (elf.ehdrField(.type)) { | 1206 | break :ph_vaddr switch (elf.ehdrField(.type)) { |
| 980 | .NONE, .CORE, _ => unreachable, | 1207 | .NONE, .CORE, _ => unreachable, |
| 981 | .REL, .DYN => 0, | 1208 | .REL, .DYN => 0, |
| 982 | .EXEC => switch (elf.ehdrField(.machine)) { | 1209 | .EXEC => switch (machine) { |
| 983 | .@"386" => 0x400000, | 1210 | .@"386" => 0x400000, |
| 984 | .AARCH64, .X86_64 => 0x200000, | 1211 | .AARCH64, .X86_64 => 0x200000, |
| 985 | .PPC, .PPC64 => 0x10000000, | 1212 | .PPC, .PPC64 => 0x10000000, |
| ... | @@ -1070,35 +1297,48 @@ fn initHeaders( | ... | @@ -1070,35 +1297,48 @@ fn initHeaders( |
| 1070 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); | 1297 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_data); |
| 1071 | ph_vaddr += @intCast(data_size); | 1298 | ph_vaddr += @intCast(data_size); |
| 1072 | | 1299 | |
| 1073 | if (have_dynamic_section) { | 1300 | if (comp.config.any_non_single_threaded) { |
| 1074 | const ph_dynamic = &phdr[dynamic_phndx]; | 1301 | const ph_tls = &phdr[tls_phndx]; |
| 1075 | ph_dynamic.* = .{ | 1302 | ph_tls.* = .{ |
| 1076 | .type = .DYNAMIC, | 1303 | .type = .TLS, |
| 1077 | .offset = 0, | 1304 | .offset = 0, |
| 1078 | .vaddr = 0, | 1305 | .vaddr = 0, |
| 1079 | .paddr = 0, | 1306 | .paddr = 0, |
| 1080 | .filesz = 0, | 1307 | .filesz = 0, |
| 1081 | .memsz = 0, | 1308 | .memsz = 0, |
| 1082 | .flags = .{ .R = true, .W = true }, | 1309 | .flags = .{ .R = true }, |
| 1083 | .@"align" = @intCast(addr_align.toByteUnits()), | 1310 | .@"align" = @intCast(elf.mf.flags.block_size.toByteUnits()), |
| 1084 | }; | 1311 | }; |
| 1085 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_dynamic); | 1312 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_tls); |
| 1086 | } | 1313 | } |
| 1087 | | 1314 | |
| 1088 | if (comp.config.any_non_single_threaded) { | 1315 | if (have_dynamic_section) { |
| 1089 | const ph_tls = &phdr[tls_phndx]; | 1316 | const ph_dynamic = &phdr[dynamic_phndx]; |
| 1090 | ph_tls.* = .{ | 1317 | ph_dynamic.* = .{ |
| 1091 | .type = .TLS, | 1318 | .type = .DYNAMIC, |
| 1092 | .offset = 0, | 1319 | .offset = 0, |
| 1093 | .vaddr = 0, | 1320 | .vaddr = 0, |
| 1094 | .paddr = 0, | 1321 | .paddr = 0, |
| 1095 | .filesz = 0, | 1322 | .filesz = 0, |
| 1096 | .memsz = 0, | 1323 | .memsz = 0, |
| 1097 | .flags = .{ .R = true }, | 1324 | .flags = .{ .R = true, .W = true }, |
| 1098 | .@"align" = @intCast(elf.mf.flags.block_size.toByteUnits()), | 1325 | .@"align" = @intCast(addr_align.toByteUnits()), |
| 1099 | }; | 1326 | }; |
| 1100 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_tls); | 1327 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_dynamic); |
| 1101 | } | 1328 | } |
| | 1329 | |
| | 1330 | const ph_relro = &phdr[relro_phndx]; |
| | 1331 | ph_relro.* = .{ |
| | 1332 | .type = .GNU_RELRO, |
| | 1333 | .offset = 0, |
| | 1334 | .vaddr = 0, |
| | 1335 | .paddr = 0, |
| | 1336 | .filesz = 0, |
| | 1337 | .memsz = 0, |
| | 1338 | .flags = .{ .R = true }, |
| | 1339 | .@"align" = @intCast(elf.mf.flags.block_size.toByteUnits()), |
| | 1340 | }; |
| | 1341 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Phdr, ph_relro); |
| 1102 | } | 1342 | } |
| 1103 | | 1343 | |
| 1104 | const sh_undef: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf))); | 1344 | const sh_undef: *ElfN.Shdr = @ptrCast(@alignCast(elf.ni.shdr.slice(&elf.mf))); |
| ... | @@ -1117,7 +1357,6 @@ fn initHeaders( | ... | @@ -1117,7 +1357,6 @@ fn initHeaders( |
| 1117 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef); | 1357 | if (target_endian != native_endian) std.mem.byteSwapAllFields(ElfN.Shdr, sh_undef); |
| 1118 | elf.shdrs.appendAssumeCapacity(.{ .si = .null, .rela_si = .null, .rela_free = .none }); | 1358 | elf.shdrs.appendAssumeCapacity(.{ .si = .null, .rela_si = .null, .rela_free = .none }); |
| 1119 | | 1359 | |
| 1120 | try elf.symtab.ensureTotalCapacity(gpa, 1); | | |
| 1121 | elf.symtab.addOneAssumeCapacity().* = .{ | 1360 | elf.symtab.addOneAssumeCapacity().* = .{ |
| 1122 | .ni = .none, | 1361 | .ni = .none, |
| 1123 | .loc_relocs = .none, | 1362 | .loc_relocs = .none, |
| ... | @@ -1163,7 +1402,9 @@ fn initHeaders( | ... | @@ -1163,7 +1402,9 @@ fn initHeaders( |
| 1163 | .entsize = 1, | 1402 | .entsize = 1, |
| 1164 | .node_align = elf.mf.flags.block_size, | 1403 | .node_align = elf.mf.flags.block_size, |
| 1165 | })); | 1404 | })); |
| 1166 | try elf.linkSections(.symtab, .strtab); | 1405 | switch (elf.shdrPtr(elf.si.symtab.shndx(elf))) { |
| | 1406 | inline else => |shdr| elf.targetStore(&shdr.link, @intFromEnum(elf.si.strtab.shndx(elf))), |
| | 1407 | } |
| 1167 | elf.si.strtab.node(elf).slice(&elf.mf)[0] = 0; | 1408 | elf.si.strtab.node(elf).slice(&elf.mf)[0] = 0; |
| 1168 | | 1409 | |
| 1169 | assert(elf.si.rodata == try elf.addSection(elf.ni.rodata, .{ | 1410 | assert(elf.si.rodata == try elf.addSection(elf.ni.rodata, .{ |
| ... | @@ -1181,7 +1422,50 @@ fn initHeaders( | ... | @@ -1181,7 +1422,50 @@ fn initHeaders( |
| 1181 | .flags = .{ .WRITE = true, .ALLOC = true }, | 1422 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 1182 | .addralign = elf.mf.flags.block_size, | 1423 | .addralign = elf.mf.flags.block_size, |
| 1183 | })); | 1424 | })); |
| | 1425 | assert(elf.si.data_rel_ro == try elf.addSection(elf.ni.data_rel_ro, .{ |
| | 1426 | .name = ".data.rel.ro", |
| | 1427 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| | 1428 | .addralign = elf.mf.flags.block_size, |
| | 1429 | })); |
| 1184 | if (@"type" != .REL) { | 1430 | if (@"type" != .REL) { |
| | 1431 | assert(elf.si.got == try elf.addSection(elf.ni.data_rel_ro, .{ |
| | 1432 | .name = ".got", |
| | 1433 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| | 1434 | .addralign = addr_align, |
| | 1435 | })); |
| | 1436 | assert(elf.si.got_plt == try elf.addSection( |
| | 1437 | if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data, |
| | 1438 | .{ |
| | 1439 | .name = ".got.plt", |
| | 1440 | .type = .PROGBITS, |
| | 1441 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| | 1442 | .size = switch (machine) { |
| | 1443 | else => @panic(@tagName(machine)), |
| | 1444 | .@"386" => 3 * 4, |
| | 1445 | .X86_64 => 3 * 8, |
| | 1446 | }, |
| | 1447 | .addralign = addr_align, |
| | 1448 | }, |
| | 1449 | )); |
| | 1450 | const plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const plt_sec = |
| | 1451 | switch (machine) { |
| | 1452 | else => @panic(@tagName(machine)), |
| | 1453 | .X86_64 => .{ 16, .@"16", true }, |
| | 1454 | }; |
| | 1455 | assert(elf.si.plt == try elf.addSection(elf.ni.text, .{ |
| | 1456 | .name = ".plt", |
| | 1457 | .type = .PROGBITS, |
| | 1458 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, |
| | 1459 | .size = plt_size, |
| | 1460 | .addralign = plt_align, |
| | 1461 | .node_align = elf.mf.flags.block_size, |
| | 1462 | })); |
| | 1463 | if (plt_sec) assert(elf.si.plt_sec == try elf.addSection(elf.ni.text, .{ |
| | 1464 | .name = ".plt.sec", |
| | 1465 | .flags = .{ .ALLOC = true, .EXECINSTR = true }, |
| | 1466 | .addralign = plt_align, |
| | 1467 | .node_align = elf.mf.flags.block_size, |
| | 1468 | })); |
| 1185 | if (maybe_interp) |interp| { | 1469 | if (maybe_interp) |interp| { |
| 1186 | const interp_ni = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{ | 1470 | const interp_ni = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{ |
| 1187 | .size = interp.len + 1, | 1471 | .size = interp.len + 1, |
| ... | @@ -1193,8 +1477,8 @@ fn initHeaders( | ... | @@ -1193,8 +1477,8 @@ fn initHeaders( |
| 1193 | elf.phdrs.items[interp_phndx] = interp_ni; | 1477 | elf.phdrs.items[interp_phndx] = interp_ni; |
| 1194 | | 1478 | |
| 1195 | const sec_interp_si = try elf.addSection(interp_ni, .{ | 1479 | const sec_interp_si = try elf.addSection(interp_ni, .{ |
| 1196 | .type = .PROGBITS, | | |
| 1197 | .name = ".interp", | 1480 | .name = ".interp", |
| | 1481 | .type = .PROGBITS, |
| 1198 | .flags = .{ .ALLOC = true }, | 1482 | .flags = .{ .ALLOC = true }, |
| 1199 | .size = @intCast(interp.len + 1), | 1483 | .size = @intCast(interp.len + 1), |
| 1200 | }); | 1484 | }); |
| ... | @@ -1203,13 +1487,24 @@ fn initHeaders( | ... | @@ -1203,13 +1487,24 @@ fn initHeaders( |
| 1203 | sec_interp[interp.len] = 0; | 1487 | sec_interp[interp.len] = 0; |
| 1204 | } | 1488 | } |
| 1205 | if (have_dynamic_section) { | 1489 | if (have_dynamic_section) { |
| 1206 | const dynamic_ni = try elf.mf.addLastChildNode(gpa, elf.ni.data, .{ | 1490 | const dynamic_ni = try elf.mf.addLastChildNode(gpa, elf.ni.data_rel_ro, .{ |
| | 1491 | .alignment = addr_align, |
| 1207 | .moved = true, | 1492 | .moved = true, |
| 1208 | .bubbles_moved = false, | 1493 | .bubbles_moved = false, |
| 1209 | }); | 1494 | }); |
| 1210 | elf.nodes.appendAssumeCapacity(.{ .segment = dynamic_phndx }); | 1495 | elf.nodes.appendAssumeCapacity(.{ .segment = dynamic_phndx }); |
| 1211 | elf.phdrs.items[dynamic_phndx] = dynamic_ni; | 1496 | elf.phdrs.items[dynamic_phndx] = dynamic_ni; |
| 1212 | | 1497 | |
| | 1498 | elf.si.dynstr = try elf.addSection(elf.ni.rodata, .{ |
| | 1499 | .name = ".dynstr", |
| | 1500 | .type = .STRTAB, |
| | 1501 | .flags = .{ .ALLOC = true }, |
| | 1502 | .size = 1, |
| | 1503 | .entsize = 1, |
| | 1504 | .node_align = elf.mf.flags.block_size, |
| | 1505 | }); |
| | 1506 | const dynstr_shndx = elf.si.dynstr.shndx(elf); |
| | 1507 | elf.dynsym.putAssumeCapacityNoClobber(.null, {}); |
| 1213 | switch (class) { | 1508 | switch (class) { |
| 1214 | .NONE, _ => unreachable, | 1509 | .NONE, _ => unreachable, |
| 1215 | inline else => |ct_class| { | 1510 | inline else => |ct_class| { |
| ... | @@ -1217,7 +1512,10 @@ fn initHeaders( | ... | @@ -1217,7 +1512,10 @@ fn initHeaders( |
| 1217 | elf.si.dynsym = try elf.addSection(elf.ni.rodata, .{ | 1512 | elf.si.dynsym = try elf.addSection(elf.ni.rodata, .{ |
| 1218 | .name = ".dynsym", | 1513 | .name = ".dynsym", |
| 1219 | .type = .DYNSYM, | 1514 | .type = .DYNSYM, |
| | 1515 | .flags = .{ .ALLOC = true }, |
| 1220 | .size = @sizeOf(Sym) * 1, | 1516 | .size = @sizeOf(Sym) * 1, |
| | 1517 | .link = @intFromEnum(dynstr_shndx), |
| | 1518 | .info = 1, |
| 1221 | .addralign = addr_align, | 1519 | .addralign = addr_align, |
| 1222 | .entsize = @sizeOf(Sym), | 1520 | .entsize = @sizeOf(Sym), |
| 1223 | .node_align = elf.mf.flags.block_size, | 1521 | .node_align = elf.mf.flags.block_size, |
| ... | @@ -1237,21 +1535,66 @@ fn initHeaders( | ... | @@ -1237,21 +1535,66 @@ fn initHeaders( |
| 1237 | ); | 1535 | ); |
| 1238 | }, | 1536 | }, |
| 1239 | } | 1537 | } |
| 1240 | elf.si.dynstr = try elf.addSection(elf.ni.rodata, .{ | 1538 | const rela_size: std.elf.Word = switch (class) { |
| 1241 | .name = ".dynstr", | 1539 | .NONE, _ => unreachable, |
| 1242 | .type = .STRTAB, | 1540 | inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela), |
| 1243 | .size = 1, | 1541 | }; |
| 1244 | .entsize = 1, | 1542 | elf.si.got.shndx(elf).get(elf).rela_si = try elf.addSection(elf.ni.rodata, .{ |
| | 1543 | .name = ".rela.dyn", |
| | 1544 | .type = .RELA, |
| | 1545 | .flags = .{ .ALLOC = true }, |
| | 1546 | .link = @intFromEnum(elf.si.dynsym.shndx(elf)), |
| | 1547 | .addralign = addr_align, |
| | 1548 | .entsize = rela_size, |
| | 1549 | .node_align = elf.mf.flags.block_size, |
| | 1550 | }); |
| | 1551 | const got_plt_shndx = elf.si.got_plt.shndx(elf); |
| | 1552 | got_plt_shndx.get(elf).rela_si = try elf.addSection(elf.ni.rodata, .{ |
| | 1553 | .name = ".rela.plt", |
| | 1554 | .type = .RELA, |
| | 1555 | .flags = .{ .ALLOC = true, .INFO_LINK = true }, |
| | 1556 | .link = @intFromEnum(elf.si.dynsym.shndx(elf)), |
| | 1557 | .info = @intFromEnum(got_plt_shndx), |
| | 1558 | .addralign = addr_align, |
| | 1559 | .entsize = rela_size, |
| 1245 | .node_align = elf.mf.flags.block_size, | 1560 | .node_align = elf.mf.flags.block_size, |
| 1246 | }); | 1561 | }); |
| 1247 | elf.si.dynamic = try elf.addSection(dynamic_ni, .{ | 1562 | elf.si.dynamic = try elf.addSection(dynamic_ni, .{ |
| 1248 | .name = ".dynamic", | 1563 | .name = ".dynamic", |
| 1249 | .type = .DYNAMIC, | 1564 | .type = .DYNAMIC, |
| 1250 | .flags = .{ .ALLOC = true, .WRITE = true }, | 1565 | .flags = .{ .ALLOC = true, .WRITE = true }, |
| | 1566 | .link = @intFromEnum(dynstr_shndx), |
| | 1567 | .entsize = @intCast(addr_align.toByteUnits() * 2), |
| 1251 | .node_align = addr_align, | 1568 | .node_align = addr_align, |
| 1252 | }); | 1569 | }); |
| 1253 | try elf.linkSections(elf.si.dynamic, elf.si.dynstr); | 1570 | switch (machine) { |
| 1254 | try elf.linkSections(elf.si.dynsym, elf.si.dynstr); | 1571 | else => @panic(@tagName(machine)), |
| | 1572 | .X86_64 => { |
| | 1573 | @memcpy(elf.si.plt.node(elf).slice(&elf.mf)[0..16], &[16]u8{ |
| | 1574 | 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // push 0x0(%rip) |
| | 1575 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *0x0(%rip) |
| | 1576 | 0x0f, 0x1f, 0x40, 0x00, // nopl 0x0(%rax) |
| | 1577 | }); |
| | 1578 | const plt_sym = elf.si.plt.get(elf); |
| | 1579 | assert(plt_sym.loc_relocs == .none); |
| | 1580 | plt_sym.loc_relocs = @enumFromInt(elf.relocs.items.len); |
| | 1581 | try elf.ensureUnusedRelocCapacity(elf.si.plt, 2); |
| | 1582 | elf.addRelocAssumeCapacity( |
| | 1583 | elf.si.plt, |
| | 1584 | 2, |
| | 1585 | elf.si.got_plt, |
| | 1586 | 8 * 1 - 4, |
| | 1587 | .{ .X86_64 = .PC32 }, |
| | 1588 | ); |
| | 1589 | elf.addRelocAssumeCapacity( |
| | 1590 | elf.si.plt, |
| | 1591 | 8, |
| | 1592 | elf.si.got_plt, |
| | 1593 | 8 * 2 - 4, |
| | 1594 | .{ .X86_64 = .PC32 }, |
| | 1595 | ); |
| | 1596 | }, |
| | 1597 | } |
| 1255 | } | 1598 | } |
| 1256 | if (comp.config.any_non_single_threaded) { | 1599 | if (comp.config.any_non_single_threaded) { |
| 1257 | elf.ni.tls = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{ | 1600 | elf.ni.tls = try elf.mf.addLastChildNode(gpa, elf.ni.rodata, .{ |
| ... | @@ -1305,7 +1648,8 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node { | ... | @@ -1305,7 +1648,8 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node { |
| 1305 | } | 1648 | } |
| 1306 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { | 1649 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 1307 | const parent_vaddr = parent_vaddr: { | 1650 | const parent_vaddr = parent_vaddr: { |
| 1308 | const parent_si = switch (elf.getNode(ni.parent(&elf.mf))) { | 1651 | const parent_ni = ni.parent(&elf.mf); |
| | 1652 | const parent_si = switch (elf.getNode(parent_ni)) { |
| 1309 | .file => return 0, | 1653 | .file => return 0, |
| 1310 | .ehdr, .shdr => unreachable, | 1654 | .ehdr, .shdr => unreachable, |
| 1311 | .segment => |phndx| break :parent_vaddr switch (elf.phdrSlice()) { | 1655 | .segment => |phndx| break :parent_vaddr switch (elf.phdrSlice()) { |
| ... | @@ -1630,7 +1974,7 @@ pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index { | ... | @@ -1630,7 +1974,7 @@ pub fn lazySymbol(elf: *Elf, lazy: link.File.LazySymbol) !Symbol.Index { |
| 1630 | } | 1974 | } |
| 1631 | | 1975 | |
| 1632 | pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || | 1976 | pub fn loadInput(elf: *Elf, input: link.Input) (std.fs.File.Reader.SizeError || |
| 1633 | std.Io.File.Reader.Error || MappedFile.Error || error{ EndOfStream, LinkFailure })!void { | 1977 | std.Io.File.Reader.Error || MappedFile.Error || error{ EndOfStream, BadMagic, LinkFailure })!void { |
| 1634 | const io = elf.base.comp.io; | 1978 | const io = elf.base.comp.io; |
| 1635 | var buf: [4096]u8 = undefined; | 1979 | var buf: [4096]u8 = undefined; |
| 1636 | switch (input) { | 1980 | switch (input) { |
| ... | @@ -1670,8 +2014,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) ! | ... | @@ -1670,8 +2014,7 @@ fn loadArchive(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) ! |
| 1670 | const r = &fr.interface; | 2014 | const r = &fr.interface; |
| 1671 | | 2015 | |
| 1672 | log.debug("loadArchive({f})", .{path.fmtEscapeString()}); | 2016 | log.debug("loadArchive({f})", .{path.fmtEscapeString()}); |
| 1673 | if (!std.mem.eql(u8, try r.take(std.elf.ARMAG.len), std.elf.ARMAG)) | 2017 | if (!std.mem.eql(u8, try r.take(std.elf.ARMAG.len), std.elf.ARMAG)) return error.BadMagic; |
| 1674 | return diags.failParse(path, "bad magic", .{}); | | |
| 1675 | var strtab: std.Io.Writer.Allocating = .init(gpa); | 2018 | var strtab: std.Io.Writer.Allocating = .init(gpa); |
| 1676 | defer strtab.deinit(); | 2019 | defer strtab.deinit(); |
| 1677 | while (r.takeStruct(std.elf.ar_hdr, native_endian)) |header| { | 2020 | while (r.takeStruct(std.elf.ar_hdr, native_endian)) |header| { |
| ... | @@ -1734,8 +2077,9 @@ fn loadObject( | ... | @@ -1734,8 +2077,9 @@ fn loadObject( |
| 1734 | | 2077 | |
| 1735 | const ii: Node.InputIndex = @enumFromInt(elf.inputs.items.len); | 2078 | const ii: Node.InputIndex = @enumFromInt(elf.inputs.items.len); |
| 1736 | log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberString(member) }); | 2079 | log.debug("loadObject({f}{f})", .{ path.fmtEscapeString(), fmtMemberString(member) }); |
| 1737 | const ident = try r.peek(std.elf.EI.NIDENT); | 2080 | const ident = try r.peek(std.elf.EI.OSABI); |
| 1738 | if (!std.mem.eql(u8, ident, elf.mf.contents[0..std.elf.EI.NIDENT])) | 2081 | if (!std.mem.eql(u8, ident[0..std.elf.MAGIC.len], std.elf.MAGIC)) return error.BadMagic; |
| | 2082 | if (!std.mem.eql(u8, ident[std.elf.MAGIC.len..], elf.mf.contents[std.elf.MAGIC.len..ident.len])) |
| 1739 | return diags.failParse(path, "bad ident", .{}); | 2083 | return diags.failParse(path, "bad ident", .{}); |
| 1740 | try elf.symtab.ensureUnusedCapacity(gpa, 1); | 2084 | try elf.symtab.ensureUnusedCapacity(gpa, 1); |
| 1741 | try elf.inputs.ensureUnusedCapacity(gpa, 1); | 2085 | try elf.inputs.ensureUnusedCapacity(gpa, 1); |
| ... | @@ -1973,7 +2317,8 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void | ... | @@ -1973,7 +2317,8 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *std.Io.File.Reader) !void |
| 1973 | | 2317 | |
| 1974 | log.debug("loadDso({f})", .{path.fmtEscapeString()}); | 2318 | log.debug("loadDso({f})", .{path.fmtEscapeString()}); |
| 1975 | const ident = try r.peek(std.elf.EI.NIDENT); | 2319 | const ident = try r.peek(std.elf.EI.NIDENT); |
| 1976 | if (!std.mem.eql(u8, ident, elf.mf.contents[0..std.elf.EI.NIDENT])) | 2320 | if (!std.mem.eql(u8, ident[0..std.elf.MAGIC.len], std.elf.MAGIC)) return error.BadMagic; |
| | 2321 | if (!std.mem.eql(u8, ident[std.elf.MAGIC.len..], elf.mf.contents[std.elf.MAGIC.len..ident.len])) |
| 1977 | return diags.failParse(path, "bad ident", .{}); | 2322 | return diags.failParse(path, "bad ident", .{}); |
| 1978 | const target_endian = elf.targetEndian(); | 2323 | const target_endian = elf.targetEndian(); |
| 1979 | switch (elf.identClass()) { | 2324 | switch (elf.identClass()) { |
| ... | @@ -2053,7 +2398,8 @@ pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { | ... | @@ -2053,7 +2398,8 @@ pub fn prelink(elf: *Elf, prog_node: std.Progress.Node) !void { |
| 2053 | }; | 2398 | }; |
| 2054 | } | 2399 | } |
| 2055 | fn prelinkInner(elf: *Elf) !void { | 2400 | fn prelinkInner(elf: *Elf) !void { |
| 2056 | const gpa = elf.base.comp.gpa; | 2401 | const comp = elf.base.comp; |
| | 2402 | const gpa = comp.gpa; |
| 2057 | try elf.symtab.ensureUnusedCapacity(gpa, 1); | 2403 | try elf.symtab.ensureUnusedCapacity(gpa, 1); |
| 2058 | try elf.inputs.ensureUnusedCapacity(gpa, 1); | 2404 | try elf.inputs.ensureUnusedCapacity(gpa, 1); |
| 2059 | const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{ | 2405 | const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{ |
| ... | @@ -2071,11 +2417,18 @@ fn prelinkInner(elf: *Elf) !void { | ... | @@ -2071,11 +2417,18 @@ fn prelinkInner(elf: *Elf) !void { |
| 2071 | .NONE, _ => unreachable, | 2417 | .NONE, _ => unreachable, |
| 2072 | inline else => |ct_class| { | 2418 | inline else => |ct_class| { |
| 2073 | const ElfN = ct_class.ElfN(); | 2419 | const ElfN = ct_class.ElfN(); |
| | 2420 | const flags: ElfN.Addr = if (elf.options.z_now) std.elf.DF_BIND_NOW else 0; |
| | 2421 | const flags_1: ElfN.Addr = if (elf.options.z_now) std.elf.DF_1_NOW else 0; |
| 2074 | const needed_len = elf.needed.count(); | 2422 | const needed_len = elf.needed.count(); |
| 2075 | const dynamic_len = needed_len + @intFromBool(elf.options.soname != null) + 5; | 2423 | const dynamic_len = needed_len + @intFromBool(elf.options.soname != null) + |
| | 2424 | @intFromBool(flags != 0) + @intFromBool(flags_1 != 0) + |
| | 2425 | @intFromBool(comp.config.output_mode == .Exe) + 12; |
| 2076 | const dynamic_size: u32 = @intCast(@sizeOf(ElfN.Addr) * 2 * dynamic_len); | 2426 | const dynamic_size: u32 = @intCast(@sizeOf(ElfN.Addr) * 2 * dynamic_len); |
| 2077 | const dynamic_ni = elf.si.dynamic.node(elf); | 2427 | const dynamic_ni = elf.si.dynamic.node(elf); |
| 2078 | try dynamic_ni.resize(&elf.mf, gpa, dynamic_size); | 2428 | try dynamic_ni.resize(&elf.mf, gpa, dynamic_size); |
| | 2429 | switch (elf.shdrPtr(elf.si.dynamic.shndx(elf))) { |
| | 2430 | inline else => |shdr| elf.targetStore(&shdr.size, dynamic_size), |
| | 2431 | } |
| 2079 | const sec_dynamic = dynamic_ni.slice(&elf.mf); | 2432 | const sec_dynamic = dynamic_ni.slice(&elf.mf); |
| 2080 | const dynamic_entries: [][2]ElfN.Addr = @ptrCast(@alignCast(sec_dynamic)); | 2433 | const dynamic_entries: [][2]ElfN.Addr = @ptrCast(@alignCast(sec_dynamic)); |
| 2081 | var dynamic_index: usize = 0; | 2434 | var dynamic_index: usize = 0; |
| ... | @@ -2088,14 +2441,41 @@ fn prelinkInner(elf: *Elf) !void { | ... | @@ -2088,14 +2441,41 @@ fn prelinkInner(elf: *Elf) !void { |
| 2088 | dynamic_entries[dynamic_index] = .{ std.elf.DT_SONAME, try elf.string(.dynstr, soname) }; | 2441 | dynamic_entries[dynamic_index] = .{ std.elf.DT_SONAME, try elf.string(.dynstr, soname) }; |
| 2089 | dynamic_index += 1; | 2442 | dynamic_index += 1; |
| 2090 | } | 2443 | } |
| 2091 | dynamic_entries[dynamic_index..][0..5].* = .{ | 2444 | if (flags != 0) { |
| 2092 | .{ std.elf.DT_SYMTAB, 0 }, | 2445 | dynamic_entries[dynamic_index] = .{ std.elf.DT_FLAGS, flags }; |
| | 2446 | dynamic_index += 1; |
| | 2447 | } |
| | 2448 | if (flags_1 != 0) { |
| | 2449 | dynamic_entries[dynamic_index] = .{ std.elf.DT_FLAGS_1, flags_1 }; |
| | 2450 | dynamic_index += 1; |
| | 2451 | } |
| | 2452 | if (comp.config.output_mode == .Exe) { |
| | 2453 | dynamic_entries[dynamic_index] = .{ std.elf.DT_DEBUG, 0 }; |
| | 2454 | dynamic_index += 1; |
| | 2455 | } |
| | 2456 | const rela_dyn_si = elf.si.got.shndx(elf).get(elf).rela_si; |
| | 2457 | const rela_plt_si = elf.si.got_plt.shndx(elf).get(elf).rela_si; |
| | 2458 | dynamic_entries[dynamic_index..][0..12].* = .{ |
| | 2459 | .{ std.elf.DT_RELA, @intCast(elf.computeNodeVAddr(rela_dyn_si.node(elf))) }, |
| | 2460 | .{ std.elf.DT_RELASZ, elf.targetLoad( |
| | 2461 | &@field(elf.shdrPtr(rela_dyn_si.shndx(elf)), @tagName(ct_class)).size, |
| | 2462 | ) }, |
| | 2463 | .{ std.elf.DT_RELAENT, @sizeOf(ElfN.Rela) }, |
| | 2464 | .{ std.elf.DT_JMPREL, @intCast(elf.computeNodeVAddr(rela_plt_si.node(elf))) }, |
| | 2465 | .{ std.elf.DT_PLTRELSZ, elf.targetLoad( |
| | 2466 | &@field(elf.shdrPtr(rela_plt_si.shndx(elf)), @tagName(ct_class)).size, |
| | 2467 | ) }, |
| | 2468 | .{ std.elf.DT_PLTGOT, @intCast(elf.computeNodeVAddr(elf.si.got_plt.node(elf))) }, |
| | 2469 | .{ std.elf.DT_PLTREL, std.elf.DT_RELA }, |
| | 2470 | .{ std.elf.DT_SYMTAB, @intCast(elf.computeNodeVAddr(elf.si.dynsym.node(elf))) }, |
| 2093 | .{ std.elf.DT_SYMENT, @sizeOf(ElfN.Sym) }, | 2471 | .{ std.elf.DT_SYMENT, @sizeOf(ElfN.Sym) }, |
| 2094 | .{ std.elf.DT_STRTAB, 0 }, | 2472 | .{ std.elf.DT_STRTAB, @intCast(elf.computeNodeVAddr(elf.si.dynstr.node(elf))) }, |
| 2095 | .{ std.elf.DT_STRSZ, 0 }, | 2473 | .{ std.elf.DT_STRSZ, elf.targetLoad( |
| | 2474 | &@field(elf.shdrPtr(elf.si.dynstr.shndx(elf)), @tagName(ct_class)).size, |
| | 2475 | ) }, |
| 2096 | .{ std.elf.DT_NULL, 0 }, | 2476 | .{ std.elf.DT_NULL, 0 }, |
| 2097 | }; | 2477 | }; |
| 2098 | dynamic_index += 5; | 2478 | dynamic_index += 12; |
| 2099 | assert(dynamic_index == dynamic_len); | 2479 | assert(dynamic_index == dynamic_len); |
| 2100 | if (elf.targetEndian() != native_endian) for (dynamic_entries) |*dynamic_entry| | 2480 | if (elf.targetEndian() != native_endian) for (dynamic_entries) |*dynamic_entry| |
| 2101 | std.mem.byteSwapAllFields(@TypeOf(dynamic_entry.*), dynamic_entry); | 2481 | std.mem.byteSwapAllFields(@TypeOf(dynamic_entry.*), dynamic_entry); |
| ... | @@ -2103,26 +2483,41 @@ fn prelinkInner(elf: *Elf) !void { | ... | @@ -2103,26 +2483,41 @@ fn prelinkInner(elf: *Elf) !void { |
| 2103 | const dynamic_sym = elf.si.dynamic.get(elf); | 2483 | const dynamic_sym = elf.si.dynamic.get(elf); |
| 2104 | assert(dynamic_sym.loc_relocs == .none); | 2484 | assert(dynamic_sym.loc_relocs == .none); |
| 2105 | dynamic_sym.loc_relocs = @enumFromInt(elf.relocs.items.len); | 2485 | dynamic_sym.loc_relocs = @enumFromInt(elf.relocs.items.len); |
| 2106 | try elf.addReloc( | 2486 | try elf.ensureUnusedRelocCapacity(elf.si.dynamic, 5); |
| | 2487 | elf.addRelocAssumeCapacity( |
| 2107 | elf.si.dynamic, | 2488 | elf.si.dynamic, |
| 2108 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 5) + 1), | 2489 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 12) + 1), |
| 2109 | elf.si.dynsym, | 2490 | rela_dyn_si, |
| 2110 | 0, | 2491 | 0, |
| 2111 | .absAddr(elf), | 2492 | .absAddr(elf), |
| 2112 | ); | 2493 | ); |
| 2113 | try elf.addReloc( | 2494 | elf.addRelocAssumeCapacity( |
| 2114 | elf.si.dynamic, | 2495 | elf.si.dynamic, |
| 2115 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 3) + 1), | 2496 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 9) + 1), |
| 2116 | elf.si.dynstr, | 2497 | rela_plt_si, |
| 2117 | 0, | 2498 | 0, |
| 2118 | .absAddr(elf), | 2499 | .absAddr(elf), |
| 2119 | ); | 2500 | ); |
| 2120 | try elf.addReloc( | 2501 | elf.addRelocAssumeCapacity( |
| 2121 | elf.si.dynamic, | 2502 | elf.si.dynamic, |
| 2122 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 2) + 1), | 2503 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 7) + 1), |
| | 2504 | elf.si.got_plt, |
| | 2505 | 0, |
| | 2506 | .absAddr(elf), |
| | 2507 | ); |
| | 2508 | elf.addRelocAssumeCapacity( |
| | 2509 | elf.si.dynamic, |
| | 2510 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 5) + 1), |
| | 2511 | elf.si.dynsym, |
| | 2512 | 0, |
| | 2513 | .absAddr(elf), |
| | 2514 | ); |
| | 2515 | elf.addRelocAssumeCapacity( |
| | 2516 | elf.si.dynamic, |
| | 2517 | @sizeOf(ElfN.Addr) * (2 * (dynamic_len - 3) + 1), |
| 2123 | elf.si.dynstr, | 2518 | elf.si.dynstr, |
| 2124 | 0, | 2519 | 0, |
| 2125 | .sizeAddr(elf), | 2520 | .absAddr(elf), |
| 2126 | ); | 2521 | ); |
| 2127 | }, | 2522 | }, |
| 2128 | }; | 2523 | }; |
| ... | @@ -2168,6 +2563,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -2168,6 +2563,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 2168 | addralign: std.mem.Alignment = .@"1", | 2563 | addralign: std.mem.Alignment = .@"1", |
| 2169 | entsize: std.elf.Word = 0, | 2564 | entsize: std.elf.Word = 0, |
| 2170 | node_align: std.mem.Alignment = .@"1", | 2565 | node_align: std.mem.Alignment = .@"1", |
| | 2566 | fixed: bool = false, |
| 2171 | }) !Symbol.Index { | 2567 | }) !Symbol.Index { |
| 2172 | switch (opts.type) { | 2568 | switch (opts.type) { |
| 2173 | .NULL => assert(opts.size == 0), | 2569 | .NULL => assert(opts.size == 0), |
| ... | @@ -2215,8 +2611,9 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { | ... | @@ -2215,8 +2611,9 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 2215 | .REL => elf.ni.file, | 2611 | .REL => elf.ni.file, |
| 2216 | .EXEC, .DYN => segment_ni, | 2612 | .EXEC, .DYN => segment_ni, |
| 2217 | }, .{ | 2613 | }, .{ |
| 2218 | .alignment = opts.addralign.max(opts.node_align), | | |
| 2219 | .size = opts.size, | 2614 | .size = opts.size, |
| | 2615 | .alignment = opts.addralign.max(opts.node_align), |
| | 2616 | .fixed = opts.fixed, |
| 2220 | .resized = opts.size > 0, | 2617 | .resized = opts.size > 0, |
| 2221 | }); | 2618 | }); |
| 2222 | const si = elf.addSymbolAssumeCapacity(); | 2619 | const si = elf.addSymbolAssumeCapacity(); |
| ... | @@ -2253,12 +2650,6 @@ fn renameSection(elf: *Elf, si: Symbol.Index, name: []const u8) !void { | ... | @@ -2253,12 +2650,6 @@ fn renameSection(elf: *Elf, si: Symbol.Index, name: []const u8) !void { |
| 2253 | } | 2650 | } |
| 2254 | } | 2651 | } |
| 2255 | | 2652 | |
| 2256 | fn linkSections(elf: *Elf, si: Symbol.Index, link_si: Symbol.Index) !void { | | |
| 2257 | switch (elf.shdrPtr(si.shndx(elf))) { | | |
| 2258 | inline else => |shdr| elf.targetStore(&shdr.link, @intFromEnum(link_si.shndx(elf))), | | |
| 2259 | } | | |
| 2260 | } | | |
| 2261 | | | |
| 2262 | fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 { | 2653 | fn sectionName(elf: *Elf, si: Symbol.Index) [:0]const u8 { |
| 2263 | const name = elf.si.shstrtab.node(elf).slice(&elf.mf)[switch (elf.shdrPtr(si.shndx(elf))) { | 2654 | const name = elf.si.shstrtab.node(elf).slice(&elf.mf)[switch (elf.shdrPtr(si.shndx(elf))) { |
| 2264 | inline else => |shdr| elf.targetLoad(&shdr.name), | 2655 | inline else => |shdr| elf.targetLoad(&shdr.name), |
| ... | @@ -2285,41 +2676,60 @@ pub fn addReloc( | ... | @@ -2285,41 +2676,60 @@ pub fn addReloc( |
| 2285 | pub fn ensureUnusedRelocCapacity(elf: *Elf, loc_si: Symbol.Index, len: usize) !void { | 2676 | pub fn ensureUnusedRelocCapacity(elf: *Elf, loc_si: Symbol.Index, len: usize) !void { |
| 2286 | if (len == 0) return; | 2677 | if (len == 0) return; |
| 2287 | const gpa = elf.base.comp.gpa; | 2678 | const gpa = elf.base.comp.gpa; |
| 2288 | | | |
| 2289 | try elf.relocs.ensureUnusedCapacity(gpa, len); | 2679 | try elf.relocs.ensureUnusedCapacity(gpa, len); |
| 2290 | if (elf.ehdrField(.type) != .REL) return; | 2680 | const class = elf.identClass(); |
| 2291 | | 2681 | const rela_si, const rela_len = rela: switch (elf.ehdrField(.type)) { |
| 2292 | const shndx = loc_si.shndx(elf); | 2682 | .NONE, .CORE, _ => unreachable, |
| 2293 | const sh = shndx.get(elf); | 2683 | .REL => { |
| 2294 | if (sh.rela_si == .null) { | 2684 | const shndx = loc_si.shndx(elf); |
| 2295 | var stack = std.heap.stackFallback(32, gpa); | 2685 | const sh = shndx.get(elf); |
| 2296 | const allocator = stack.get(); | 2686 | if (sh.rela_si == .null) { |
| 2297 | | 2687 | var stack = std.heap.stackFallback(32, gpa); |
| 2298 | const rela_name = try std.fmt.allocPrint(allocator, ".rela{s}", .{elf.sectionName(sh.si)}); | 2688 | const allocator = stack.get(); |
| 2299 | defer allocator.free(rela_name); | 2689 | |
| 2300 | | 2690 | const rela_name = |
| 2301 | const class = elf.identClass(); | 2691 | try std.fmt.allocPrint(allocator, ".rela{s}", .{elf.sectionName(sh.si)}); |
| 2302 | sh.rela_si = try elf.addSection(.none, .{ | 2692 | defer allocator.free(rela_name); |
| 2303 | .name = rela_name, | 2693 | |
| 2304 | .type = .RELA, | 2694 | sh.rela_si = try elf.addSection(.none, .{ |
| 2305 | .link = @intFromEnum(elf.si.symtab.shndx(elf)), | 2695 | .name = rela_name, |
| 2306 | .info = @intFromEnum(shndx), | 2696 | .type = .RELA, |
| 2307 | .addralign = switch (class) { | 2697 | .link = @intFromEnum(elf.si.symtab.shndx(elf)), |
| 2308 | .NONE, _ => unreachable, | 2698 | .info = @intFromEnum(shndx), |
| 2309 | .@"32" => .@"4", | 2699 | .addralign = switch (class) { |
| 2310 | .@"64" => .@"8", | 2700 | .NONE, _ => unreachable, |
| 2311 | }, | 2701 | .@"32" => .@"4", |
| 2312 | .entsize = switch (class) { | 2702 | .@"64" => .@"8", |
| 2313 | .NONE, _ => unreachable, | 2703 | }, |
| 2314 | inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela), | 2704 | .entsize = switch (class) { |
| 2315 | }, | 2705 | .NONE, _ => unreachable, |
| 2316 | .node_align = elf.mf.flags.block_size, | 2706 | inline else => |ct_class| @sizeOf(ct_class.ElfN().Rela), |
| 2317 | }); | 2707 | }, |
| 2318 | } | 2708 | .node_align = elf.mf.flags.block_size, |
| 2319 | const rela_ni = sh.rela_si.node(elf); | 2709 | }); |
| | 2710 | } |
| | 2711 | break :rela .{ sh.rela_si, len }; |
| | 2712 | }, |
| | 2713 | .EXEC, .DYN => switch (elf.got.tlsld) { |
| | 2714 | _ => return, |
| | 2715 | .none => if (elf.si.dynamic != .null) { |
| | 2716 | try elf.mf.updates.ensureUnusedCapacity(gpa, 1); |
| | 2717 | const got_ni = elf.si.got.node(elf); |
| | 2718 | _, const got_node_size = got_ni.location(&elf.mf).resolve(&elf.mf); |
| | 2719 | const got_size = switch (class) { |
| | 2720 | .NONE, _ => unreachable, |
| | 2721 | inline else => |ct_class| (elf.got.len + 2) * @sizeOf(ct_class.ElfN().Addr), |
| | 2722 | }; |
| | 2723 | if (got_size > got_node_size) |
| | 2724 | try got_ni.resize(&elf.mf, gpa, got_size +| got_size / MappedFile.growth_factor); |
| | 2725 | break :rela .{ elf.si.got.shndx(elf).get(elf).rela_si, 1 }; |
| | 2726 | } else return, |
| | 2727 | }, |
| | 2728 | }; |
| | 2729 | const rela_ni = rela_si.node(elf); |
| 2320 | _, const rela_node_size = rela_ni.location(&elf.mf).resolve(&elf.mf); | 2730 | _, const rela_node_size = rela_ni.location(&elf.mf).resolve(&elf.mf); |
| 2321 | const rela_size = switch (elf.shdrPtr(sh.rela_si.shndx(elf))) { | 2731 | const rela_size = switch (elf.shdrPtr(rela_si.shndx(elf))) { |
| 2322 | inline else => |shdr| elf.targetLoad(&shdr.size) + elf.targetLoad(&shdr.entsize) * len, | 2732 | inline else => |shdr| elf.targetLoad(&shdr.size) + elf.targetLoad(&shdr.entsize) * rela_len, |
| 2323 | }; | 2733 | }; |
| 2324 | if (rela_size > rela_node_size) | 2734 | if (rela_size > rela_node_size) |
| 2325 | try rela_ni.resize(&elf.mf, gpa, rela_size +| rela_size / MappedFile.growth_factor); | 2735 | try rela_ni.resize(&elf.mf, gpa, rela_size +| rela_size / MappedFile.growth_factor); |
| ... | @@ -2377,7 +2787,59 @@ pub fn addRelocAssumeCapacity( | ... | @@ -2377,7 +2787,59 @@ pub fn addRelocAssumeCapacity( |
| 2377 | }, | 2787 | }, |
| 2378 | } | 2788 | } |
| 2379 | }, | 2789 | }, |
| 2380 | .EXEC, .DYN => .none, | 2790 | .EXEC, .DYN => { |
| | 2791 | switch (elf.ehdrField(.machine)) { |
| | 2792 | else => |machine| @panic(@tagName(machine)), |
| | 2793 | .AARCH64, .PPC64, .RISCV => {}, |
| | 2794 | .X86_64 => switch (@"type".X86_64) { |
| | 2795 | else => {}, |
| | 2796 | .TLSLD => switch (elf.got.tlsld) { |
| | 2797 | _ => {}, |
| | 2798 | .none => if (elf.si.dynamic != .null) { |
| | 2799 | const tlsld_index = elf.got.len; |
| | 2800 | elf.got.tlsld = .wrap(tlsld_index); |
| | 2801 | elf.got.len = tlsld_index + 2; |
| | 2802 | const got_addr = got_addr: switch (elf.shdrPtr(elf.si.got.shndx(elf))) { |
| | 2803 | inline else => |shdr, class| { |
| | 2804 | const addr_size = @sizeOf(class.ElfN().Addr); |
| | 2805 | const old_size = addr_size * tlsld_index; |
| | 2806 | const new_size = old_size + addr_size * 2; |
| | 2807 | @memset( |
| | 2808 | elf.si.got.node(elf).slice(&elf.mf)[old_size..new_size], |
| | 2809 | 0, |
| | 2810 | ); |
| | 2811 | break :got_addr elf.targetLoad(&shdr.addr) + old_size; |
| | 2812 | }, |
| | 2813 | }; |
| | 2814 | const rela_dyn_si = elf.si.got.shndx(elf).get(elf).rela_si; |
| | 2815 | const rela_dyn_ni = rela_dyn_si.node(elf); |
| | 2816 | switch (elf.shdrPtr(rela_dyn_si.shndx(elf))) { |
| | 2817 | inline else => |shdr, class| { |
| | 2818 | const Rela = class.ElfN().Rela; |
| | 2819 | const old_size = elf.targetLoad(&shdr.size); |
| | 2820 | const new_size = old_size + elf.targetLoad(&shdr.entsize); |
| | 2821 | elf.targetStore(&shdr.size, new_size); |
| | 2822 | const rela: *Rela = @ptrCast(@alignCast(rela_dyn_ni |
| | 2823 | .slice(&elf.mf)[@intCast(old_size)..@intCast(new_size)])); |
| | 2824 | rela.* = .{ |
| | 2825 | .offset = @intCast(got_addr), |
| | 2826 | .info = .{ |
| | 2827 | .type = @intFromEnum(std.elf.R_X86_64.DTPMOD64), |
| | 2828 | .sym = 0, |
| | 2829 | }, |
| | 2830 | .addend = 0, |
| | 2831 | }; |
| | 2832 | if (elf.targetEndian() != native_endian) |
| | 2833 | std.mem.byteSwapAllFields(Rela, rela); |
| | 2834 | }, |
| | 2835 | } |
| | 2836 | rela_dyn_ni.resizedAssumeCapacity(&elf.mf); |
| | 2837 | }, |
| | 2838 | }, |
| | 2839 | }, |
| | 2840 | } |
| | 2841 | break :index .none; |
| | 2842 | }, |
| 2381 | }, | 2843 | }, |
| 2382 | .offset = offset, | 2844 | .offset = offset, |
| 2383 | .addend = addend, | 2845 | .addend = addend, |
| ... | @@ -2901,7 +3363,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { | ... | @@ -2901,7 +3363,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2901 | .NULL, .LOAD => return, | 3363 | .NULL, .LOAD => return, |
| 2902 | .DYNAMIC, .INTERP => {}, | 3364 | .DYNAMIC, .INTERP => {}, |
| 2903 | .PHDR => @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset, | 3365 | .PHDR => @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset, |
| 2904 | .TLS => {}, | 3366 | .TLS, std.elf.PT.GNU_RELRO => {}, |
| 2905 | } | 3367 | } |
| 2906 | elf.targetStore(&ph.vaddr, @intCast(elf.computeNodeVAddr(ni))); | 3368 | elf.targetStore(&ph.vaddr, @intCast(elf.computeNodeVAddr(ni))); |
| 2907 | ph.paddr = ph.vaddr; | 3369 | ph.paddr = ph.vaddr; |
| ... | @@ -2911,10 +3373,101 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { | ... | @@ -2911,10 +3373,101 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2911 | .section => |si| { | 3373 | .section => |si| { |
| 2912 | try elf.flushFileOffset(ni); | 3374 | try elf.flushFileOffset(ni); |
| 2913 | const addr = elf.computeNodeVAddr(ni); | 3375 | const addr = elf.computeNodeVAddr(ni); |
| 2914 | switch (elf.shdrPtr(si.shndx(elf))) { | 3376 | const shndx = si.shndx(elf); |
| | 3377 | switch (elf.shdrPtr(shndx)) { |
| 2915 | inline else => |shdr, class| { | 3378 | inline else => |shdr, class| { |
| 2916 | const flags = elf.targetLoad(&shdr.flags).shf; | 3379 | const flags = elf.targetLoad(&shdr.flags).shf; |
| 2917 | if (flags.ALLOC) { | 3380 | if (flags.ALLOC) { |
| | 3381 | if (elf.si.dynamic != .null) { |
| | 3382 | if (si == elf.si.got) { |
| | 3383 | const old_addr = elf.targetLoad(&shdr.addr); |
| | 3384 | const rela_dyn_si = shndx.get(elf).rela_si; |
| | 3385 | const relas: []class.ElfN().Rela = @ptrCast(@alignCast( |
| | 3386 | rela_dyn_si.node(elf).slice(&elf.mf)[0..@intCast( |
| | 3387 | elf.targetLoad(&@field( |
| | 3388 | elf.shdrPtr(rela_dyn_si.shndx(elf)), |
| | 3389 | @tagName(class), |
| | 3390 | ).size), |
| | 3391 | )], |
| | 3392 | )); |
| | 3393 | switch (elf.ehdrField(.machine)) { |
| | 3394 | else => |machine| @panic(@tagName(machine)), |
| | 3395 | .AARCH64, .PPC64, .RISCV => {}, |
| | 3396 | .X86_64 => for (relas) |*rela| switch (@as( |
| | 3397 | std.elf.R_X86_64, |
| | 3398 | @enumFromInt(elf.targetLoad(&rela.info).type), |
| | 3399 | )) { |
| | 3400 | else => |@"type"| @panic(@tagName(@"type")), |
| | 3401 | .RELATIVE => {}, |
| | 3402 | .GLOB_DAT, .DTPMOD64, .DTPOFF64 => elf.targetStore( |
| | 3403 | &rela.offset, |
| | 3404 | @intCast(elf.targetLoad(&rela.offset) - old_addr + addr), |
| | 3405 | ), |
| | 3406 | }, |
| | 3407 | } |
| | 3408 | } else if (si == elf.si.got_plt) { |
| | 3409 | const target_endian = elf.targetEndian(); |
| | 3410 | const old_addr = elf.targetLoad(&shdr.addr); |
| | 3411 | const rela_plt_si = shndx.get(elf).rela_si; |
| | 3412 | const relas: []class.ElfN().Rela = @ptrCast(@alignCast( |
| | 3413 | rela_plt_si.node(elf).slice(&elf.mf)[0..@intCast( |
| | 3414 | elf.targetLoad(&@field( |
| | 3415 | elf.shdrPtr(rela_plt_si.shndx(elf)), |
| | 3416 | @tagName(class), |
| | 3417 | ).size), |
| | 3418 | )], |
| | 3419 | )); |
| | 3420 | const plt_sec_slice = elf.si.plt_sec.node(elf).slice(&elf.mf); |
| | 3421 | switch (elf.ehdrField(.machine)) { |
| | 3422 | else => |machine| @panic(@tagName(machine)), |
| | 3423 | .AARCH64, .PPC64, .RISCV => {}, |
| | 3424 | .X86_64 => { |
| | 3425 | for (relas) |*rela| switch (@as( |
| | 3426 | std.elf.R_X86_64, |
| | 3427 | @enumFromInt(elf.targetLoad(&rela.info).type), |
| | 3428 | )) { |
| | 3429 | else => |@"type"| @panic(@tagName(@"type")), |
| | 3430 | .JUMP_SLOT => elf.targetStore( |
| | 3431 | &rela.offset, |
| | 3432 | @intCast(elf.targetLoad(&rela.offset) - old_addr + addr), |
| | 3433 | ), |
| | 3434 | }; |
| | 3435 | for (0..elf.got.plt.count()) |plt_index| { |
| | 3436 | const slice = plt_sec_slice[16 * plt_index + 6 ..][0..4]; |
| | 3437 | std.mem.writeInt( |
| | 3438 | i32, |
| | 3439 | slice, |
| | 3440 | @intCast(@as(i64, @bitCast(@as(u64, @bitCast(@as( |
| | 3441 | i64, |
| | 3442 | std.mem.readInt(i32, slice, target_endian), |
| | 3443 | ))) -% old_addr +% addr))), |
| | 3444 | target_endian, |
| | 3445 | ); |
| | 3446 | } |
| | 3447 | }, |
| | 3448 | } |
| | 3449 | } else if (si == elf.si.plt_sec) { |
| | 3450 | const target_endian = elf.targetEndian(); |
| | 3451 | const old_addr = elf.targetLoad(&shdr.addr); |
| | 3452 | const plt_sec_slice = ni.slice(&elf.mf); |
| | 3453 | switch (elf.ehdrField(.machine)) { |
| | 3454 | else => |machine| @panic(@tagName(machine)), |
| | 3455 | .AARCH64, .PPC64, .RISCV => {}, |
| | 3456 | .X86_64 => for (0..elf.got.plt.count()) |plt_index| { |
| | 3457 | const slice = plt_sec_slice[16 * plt_index + 6 ..][0..4]; |
| | 3458 | std.mem.writeInt( |
| | 3459 | i32, |
| | 3460 | slice, |
| | 3461 | @intCast(@as(i64, @bitCast(@as(u64, @bitCast(@as( |
| | 3462 | i64, |
| | 3463 | std.mem.readInt(i32, slice, target_endian), |
| | 3464 | ))) -% addr +% old_addr))), |
| | 3465 | target_endian, |
| | 3466 | ); |
| | 3467 | }, |
| | 3468 | } |
| | 3469 | } |
| | 3470 | } |
| 2918 | elf.targetStore(&shdr.addr, @intCast(addr)); | 3471 | elf.targetStore(&shdr.addr, @intCast(addr)); |
| 2919 | @field(elf.symPtr(si), @tagName(class)).value = shdr.addr; | 3472 | @field(elf.symPtr(si), @tagName(class)).value = shdr.addr; |
| 2920 | } | 3473 | } |
| ... | @@ -2960,15 +3513,21 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { | ... | @@ -2960,15 +3513,21 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2960 | const ph = &phdr[phndx]; | 3513 | const ph = &phdr[phndx]; |
| 2961 | elf.targetStore(&ph.filesz, @intCast(size)); | 3514 | elf.targetStore(&ph.filesz, @intCast(size)); |
| 2962 | if (size > elf.targetLoad(&ph.memsz)) { | 3515 | if (size > elf.targetLoad(&ph.memsz)) { |
| 2963 | const memsz = ni.alignment(&elf.mf).forward(@intCast(size * 4)); | | |
| 2964 | elf.targetStore(&ph.memsz, @intCast(memsz)); | | |
| 2965 | switch (elf.targetLoad(&ph.type)) { | 3516 | switch (elf.targetLoad(&ph.type)) { |
| 2966 | else => unreachable, | 3517 | else => unreachable, |
| 2967 | .NULL => if (size > 0) elf.targetStore(&ph.type, .LOAD), | 3518 | .NULL => if (size > 0) elf.targetStore(&ph.type, .LOAD), |
| 2968 | .LOAD => if (size == 0) elf.targetStore(&ph.type, .NULL), | 3519 | .LOAD => if (size == 0) elf.targetStore(&ph.type, .NULL), |
| 2969 | .DYNAMIC, .INTERP, .PHDR => return, | 3520 | .DYNAMIC, .INTERP, .PHDR, std.elf.PT.GNU_RELRO => { |
| 2970 | .TLS => return ni.childrenMoved(elf.base.comp.gpa, &elf.mf), | 3521 | elf.targetStore(&ph.memsz, @intCast(size)); |
| | 3522 | return; |
| | 3523 | }, |
| | 3524 | .TLS => { |
| | 3525 | elf.targetStore(&ph.memsz, @intCast(size)); |
| | 3526 | return ni.childrenMoved(elf.base.comp.gpa, &elf.mf); |
| | 3527 | }, |
| 2971 | } | 3528 | } |
| | 3529 | const memsz = ni.alignment(&elf.mf).forward(@intCast(size * 4)); |
| | 3530 | elf.targetStore(&ph.memsz, @intCast(memsz)); |
| 2972 | var vaddr = elf.targetLoad(&ph.vaddr); | 3531 | var vaddr = elf.targetLoad(&ph.vaddr); |
| 2973 | var new_phndx = phndx; | 3532 | var new_phndx = phndx; |
| 2974 | for (phdr[phndx + 1 ..], phndx + 1..) |*next_ph, next_phndx| { | 3533 | for (phdr[phndx + 1 ..], phndx + 1..) |*next_ph, next_phndx| { |
| ... | @@ -2998,18 +3557,56 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { | ... | @@ -2998,18 +3557,56 @@ fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { |
| 2998 | }, | 3557 | }, |
| 2999 | }, | 3558 | }, |
| 3000 | .section => |si| switch (elf.shdrPtr(si.shndx(elf))) { | 3559 | .section => |si| switch (elf.shdrPtr(si.shndx(elf))) { |
| 3001 | inline else => |shdr| { | 3560 | inline else => |shdr, class| { |
| 3002 | switch (elf.targetLoad(&shdr.type)) { | 3561 | switch (elf.targetLoad(&shdr.type)) { |
| 3003 | else => unreachable, | 3562 | else => unreachable, |
| 3004 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), | 3563 | .NULL => if (size > 0) elf.targetStore(&shdr.type, .PROGBITS), |
| 3005 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), | 3564 | .PROGBITS => if (size == 0) elf.targetStore(&shdr.type, .NULL), |
| 3006 | .SYMTAB, .STRTAB, .RELA, .DYNAMIC, .REL, .DYNSYM => return, | 3565 | .SYMTAB, .DYNAMIC, .REL, .DYNSYM => return, |
| | 3566 | .STRTAB => { |
| | 3567 | if (elf.si.dynamic != .null) { |
| | 3568 | if (si == elf.si.dynstr) { |
| | 3569 | const dynamic_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast( |
| | 3570 | elf.si.dynamic.node(elf).slice(&elf.mf), |
| | 3571 | )); |
| | 3572 | for (dynamic_entries) |*dynamic_entry| |
| | 3573 | switch (elf.targetLoad(&dynamic_entry[0])) { |
| | 3574 | else => {}, |
| | 3575 | std.elf.DT_STRSZ => dynamic_entry[1] = shdr.size, |
| | 3576 | }; |
| | 3577 | } |
| | 3578 | } |
| | 3579 | return; |
| | 3580 | }, |
| | 3581 | .RELA => { |
| | 3582 | if (elf.si.dynamic != .null) { |
| | 3583 | if (si == elf.si.got.shndx(elf).get(elf).rela_si) { |
| | 3584 | const dynamic_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast( |
| | 3585 | elf.si.dynamic.node(elf).slice(&elf.mf), |
| | 3586 | )); |
| | 3587 | for (dynamic_entries) |*dynamic_entry| |
| | 3588 | switch (elf.targetLoad(&dynamic_entry[0])) { |
| | 3589 | else => {}, |
| | 3590 | std.elf.DT_RELASZ => dynamic_entry[1] = shdr.size, |
| | 3591 | }; |
| | 3592 | } else if (si == elf.si.got_plt.shndx(elf).get(elf).rela_si) { |
| | 3593 | const dynamic_entries: [][2]class.ElfN().Addr = @ptrCast(@alignCast( |
| | 3594 | elf.si.dynamic.node(elf).slice(&elf.mf), |
| | 3595 | )); |
| | 3596 | for (dynamic_entries) |*dynamic_entry| |
| | 3597 | switch (elf.targetLoad(&dynamic_entry[0])) { |
| | 3598 | else => {}, |
| | 3599 | std.elf.DT_PLTRELSZ => dynamic_entry[1] = shdr.size, |
| | 3600 | }; |
| | 3601 | } |
| | 3602 | } |
| | 3603 | return; |
| | 3604 | }, |
| 3007 | } | 3605 | } |
| 3008 | elf.targetStore(&shdr.size, @intCast(size)); | 3606 | elf.targetStore(&shdr.size, @intCast(size)); |
| 3009 | }, | 3607 | }, |
| 3010 | }, | 3608 | }, |
| 3011 | .input_section => {}, | 3609 | .input_section, .nav, .uav, .lazy_code, .lazy_const_data => {}, |
| 3012 | .nav, .uav, .lazy_code, .lazy_const_data => {}, | | |
| 3013 | } | 3610 | } |
| 3014 | } | 3611 | } |
| 3015 | | 3612 | |
| ... | @@ -3069,7 +3666,11 @@ fn updateExportsInner( | ... | @@ -3069,7 +3666,11 @@ fn updateExportsInner( |
| 3069 | while (try elf.idle(pt.tid)) {} | 3666 | while (try elf.idle(pt.tid)) {} |
| 3070 | const exported_ni = exported_si.node(elf); | 3667 | const exported_ni = exported_si.node(elf); |
| 3071 | const value, const size, const shndx = switch (elf.symPtr(exported_si)) { | 3668 | const value, const size, const shndx = switch (elf.symPtr(exported_si)) { |
| 3072 | inline else => |exported_sym| .{ exported_sym.value, exported_sym.size, exported_sym.shndx }, | 3669 | inline else => |exported_sym| .{ |
| | 3670 | elf.targetLoad(&exported_sym.value), |
| | 3671 | exported_sym.size, |
| | 3672 | exported_sym.shndx, |
| | 3673 | }, |
| 3073 | }; | 3674 | }; |
| 3074 | for (export_indices) |export_index| { | 3675 | for (export_indices) |export_index| { |
| 3075 | const @"export" = export_index.ptr(zcu); | 3676 | const @"export" = export_index.ptr(zcu); |
| ... | @@ -3092,18 +3693,11 @@ fn updateExportsInner( | ... | @@ -3092,18 +3693,11 @@ fn updateExportsInner( |
| 3092 | export_si.get(elf).ni = exported_ni; | 3693 | export_si.get(elf).ni = exported_ni; |
| 3093 | switch (elf.symPtr(export_si)) { | 3694 | switch (elf.symPtr(export_si)) { |
| 3094 | inline else => |export_sym| { | 3695 | inline else => |export_sym| { |
| 3095 | export_sym.value = @intCast(value); | | |
| 3096 | export_sym.size = @intCast(size); | 3696 | export_sym.size = @intCast(size); |
| 3097 | export_sym.shndx = shndx; | 3697 | export_sym.shndx = shndx; |
| 3098 | }, | 3698 | }, |
| 3099 | } | 3699 | } |
| 3100 | export_si.applyTargetRelocs(elf); | 3700 | export_si.flushMoved(elf, value); |
| 3101 | if (std.mem.eql(u8, name, "_start")) { | | |
| 3102 | elf.entry_hack = exported_si; | | |
| 3103 | switch (elf.ehdrPtr()) { | | |
| 3104 | inline else => |ehdr| ehdr.entry = @intCast(value), | | |
| 3105 | } | | |
| 3106 | } | | |
| 3107 | } | 3701 | } |
| 3108 | } | 3702 | } |
| 3109 | | 3703 | |