@@ -164,7 +164,26 @@ pub const Node = union(enum) {
164164 }
165165};
166166
167- pub const Section = struct { si : Symbol.Index , rela_si : Symbol .Index };
167+ pub const Section = struct {
168+ si : Symbol.Index ,
169+ rela_si : Symbol.Index ,
170+ rela_free : RelIndex ,
171+
172+ pub const RelIndex = enum (u32 ) {
173+ none ,
174+ _ ,
175+
176+ pub fn wrap (i : ? u32 ) RelIndex {
177+ return @enumFromInt ((i orelse return .none ) + 1 );
178+ }
179+ pub fn unwrap (ri : RelIndex ) ? u32 {
180+ return switch (ri ) {
181+ .none = > null ,
182+ else = > @intFromEnum (ri ) - 1 ,
183+ };
184+ }
185+ };
186+ };
168187
169188pub const StringTable = struct {
170189 map : std .HashMapUnmanaged (u32 , void , StringTable .Context , std .hash_map .default_max_load_percentage ),
@@ -462,7 +481,7 @@ pub const Reloc = extern struct {
462481 next : Reloc.Index ,
463482 loc : Symbol.Index ,
464483 target : Symbol.Index ,
465- rel_index : u32 ,
484+ index : Section.RelIndex ,
466485 offset : u64 ,
467486 addend : i64 ,
468487
@@ -472,6 +491,16 @@ pub const Reloc = extern struct {
472491 RISCV : std.elf.R_RISCV ,
473492 PPC64 : std.elf.R_PPC64 ,
474493
494+ pub fn none (elf : * Elf ) Reloc.Type {
495+ return switch (elf .ehdrField (.machine )) {
496+ else = > unreachable ,
497+ .AARCH64 = > .{ .AARCH64 = .NONE },
498+ .PPC64 = > .{ .PPC64 = .NONE },
499+ .RISCV = > .{ .RISCV = .NONE },
500+ .X86_64 = > .{ .X86_64 = .NONE },
501+ };
502+ }
503+
475504 pub fn absAddr (elf : * Elf ) Reloc.Type {
476505 return switch (elf .ehdrField (.machine )) {
477506 else = > unreachable ,
@@ -481,12 +510,35 @@ pub const Reloc = extern struct {
481510 .X86_64 = > .{ .X86_64 = .@"64" },
482511 };
483512 }
513+
484514 pub fn sizeAddr (elf : * Elf ) Reloc.Type {
485515 return switch (elf .ehdrField (.machine )) {
486516 else = > unreachable ,
487517 .X86_64 = > .{ .X86_64 = .SIZE64 },
488518 };
489519 }
520+
521+ pub fn wrap (int : u32 , elf : * Elf ) Reloc.Type {
522+ return switch (elf .ehdrField (.machine )) {
523+ else = > unreachable ,
524+ inline .AARCH64 ,
525+ .PPC64 ,
526+ .RISCV ,
527+ .X86_64 ,
528+ = > | machine | @unionInit (Reloc .Type , @tagName (machine ), @enumFromInt (int )),
529+ };
530+ }
531+
532+ pub fn unwrap (rt : Reloc.Type , elf : * Elf ) u32 {
533+ return switch (elf .ehdrField (.machine )) {
534+ else = > unreachable ,
535+ inline .AARCH64 ,
536+ .PPC64 ,
537+ .RISCV ,
538+ .X86_64 ,
539+ = > | machine | @intFromEnum (@field (rt , @tagName (machine ))),
540+ };
541+ }
490542 };
491543
492544 pub const Index = enum (u32 ) {
@@ -590,6 +642,32 @@ pub const Reloc = extern struct {
590642 .none = > {},
591643 else = > | next | next .get (elf ).prev = reloc .prev ,
592644 }
645+ switch (elf .ehdrField (.type )) {
646+ .NONE , .CORE , _ = > unreachable ,
647+ .REL = > {
648+ const sh = reloc .loc .shndx (elf ).get (elf );
649+ switch (elf .shdrPtr (sh .rela_si .shndx (elf ))) {
650+ inline else = > | shdr , class | {
651+ const Rela = class .ElfN ().Rela ;
652+ const ent_size = elf .targetLoad (& shdr .entsize );
653+ const start = ent_size * reloc .index .unwrap ().? ;
654+ const rela : * Rela = @ptrCast (@alignCast (
655+ sh .rela_si .node (elf ).slice (& elf .mf )[start .. ][0.. ent_size ],
656+ ));
657+ rela .* = .{
658+ .offset = @intFromEnum (sh .rela_free ),
659+ .info = .{
660+ .type = @intCast (Reloc .Type .none (elf ).unwrap (elf )),
661+ .sym = 0 ,
662+ },
663+ .addend = 0 ,
664+ };
665+ },
666+ }
667+ sh .rela_free = reloc .index ;
668+ },
669+ .EXEC , .DYN = > assert (reloc .index == .none ),
670+ }
593671 reloc .* = undefined ;
594672 }
595673
@@ -1036,7 +1114,7 @@ fn initHeaders(
10361114 .entsize = 0 ,
10371115 };
10381116 if (target_endian != native_endian ) std .mem .byteSwapAllFields (ElfN .Shdr , sh_undef );
1039- elf .shdrs .appendAssumeCapacity (.{ .si = .null , .rela_si = .null });
1117+ elf .shdrs .appendAssumeCapacity (.{ .si = .null , .rela_si = .null , . rela_free = .none });
10401118
10411119 try elf .symtab .ensureTotalCapacity (gpa , 1 );
10421120 elf .symtab .addOneAssumeCapacity ().* = .{
@@ -1880,18 +1958,7 @@ fn loadObject(
18801958 rel .offset - loc_sec .shdr .addr ,
18811959 target_si ,
18821960 rel .addend ,
1883- switch (elf .ehdrField (.machine )) {
1884- else = > unreachable ,
1885- inline .AARCH64 ,
1886- .PPC64 ,
1887- .RISCV ,
1888- .X86_64 ,
1889- = > | machine | @unionInit (
1890- Reloc .Type ,
1891- @tagName (machine ),
1892- @enumFromInt (rel .info .type ),
1893- ),
1894- },
1961+ .wrap (rel .info .type , elf ),
18951962 );
18961963 }
18971964 },
@@ -2156,7 +2223,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct {
21562223 });
21572224 const si = elf .addSymbolAssumeCapacity ();
21582225 elf .nodes .appendAssumeCapacity (.{ .section = si });
2159- elf .shdrs .appendAssumeCapacity (.{ .si = si , .rela_si = .null });
2226+ elf .shdrs .appendAssumeCapacity (.{ .si = si , .rela_si = .null , . rela_free = .none });
21602227 si .get (elf ).ni = ni ;
21612228 const addr = elf .computeNodeVAddr (ni );
21622229 const offset = ni .fileLocation (& elf .mf , false ).offset ;
@@ -2275,39 +2342,43 @@ pub fn addRelocAssumeCapacity(
22752342 .next = target .target_relocs ,
22762343 .loc = loc_si ,
22772344 .target = target_si ,
2278- .rel_index = switch (elf .ehdrField (.type )) {
2345+ .index = index : switch (elf .ehdrField (.type )) {
22792346 .NONE , .CORE , _ = > unreachable ,
2280- .REL = > rel_index : {
2281- const rela_si = loc_si .shndx (elf ).get (elf ). rela_si ;
2282- switch (elf .shdrPtr (rela_si .shndx (elf ))) {
2347+ .REL = > {
2348+ const sh = loc_si .shndx (elf ).get (elf );
2349+ switch (elf .shdrPtr (sh . rela_si .shndx (elf ))) {
22832350 inline else = > | shdr , class | {
22842351 const Rela = class .ElfN ().Rela ;
2285- const old_size = elf .targetLoad (& shdr .size );
22862352 const ent_size = elf .targetLoad (& shdr .entsize );
2287- const new_size = old_size + ent_size ;
2288- elf .targetStore (& shdr .size , @intCast (new_size ));
2289- const rela : * Rela = @ptrCast (@alignCast (
2290- rela_si .node (elf ).slice (& elf .mf )[@intCast (old_size ).. @intCast (new_size )],
2291- ));
2353+ const rela_slice = sh .rela_si .node (elf ).slice (& elf .mf );
2354+ const index : u32 = if (sh .rela_free .unwrap ()) | index | alloc_index : {
2355+ const rela : * Rela = @ptrCast (@alignCast (
2356+ sh .rela_si .node (elf ).slice (& elf .mf )[ent_size * index .. ][0.. ent_size ],
2357+ ));
2358+ sh .rela_free = @enumFromInt (rela .offset );
2359+ break :alloc_index index ;
2360+ } else alloc_index : {
2361+ const old_size = elf .targetLoad (& shdr .size );
2362+ const new_size = old_size + ent_size ;
2363+ elf .targetStore (& shdr .size , @intCast (new_size ));
2364+ break :alloc_index @intCast (@divExact (old_size , ent_size ));
2365+ };
2366+ const rela : * Rela =
2367+ @ptrCast (@alignCast (rela_slice [ent_size * index .. ][0.. ent_size ]));
22922368 rela .* = .{
22932369 .offset = @intCast (offset ),
22942370 .info = .{
2295- .type = switch (elf .ehdrField (.machine )) {
2296- else = > | machine | @panic (@tagName (machine )),
2297- inline .X86_64 , .AARCH64 , .RISCV , .PPC64 = > | machine | @intCast (
2298- @intFromEnum (@field (@"type" , @tagName (machine ))),
2299- ),
2300- },
2371+ .type = @intCast (@"type" .unwrap (elf )),
23012372 .sym = @intCast (@intFromEnum (target_si )),
23022373 },
23032374 .addend = @intCast (addend ),
23042375 };
23052376 if (elf .targetEndian () != native_endian ) std .mem .byteSwapAllFields (Rela , rela );
2306- break :rel_index @intCast ( @divExact ( old_size , ent_size ) );
2377+ break :index . wrap ( index );
23072378 },
23082379 }
23092380 },
2310- .EXEC , .DYN = > 0 ,
2381+ .EXEC , .DYN = > .none ,
23112382 },
23122383 .offset = offset ,
23132384 .addend = addend ,
0 commit comments