@@ -30,23 +30,25 @@ atom_index: Index = 0,
30
30
prev_index : Index = 0 ,
31
31
next_index : Index = 0 ,
32
32
33
- /// Flags we use for state tracking.
34
- flags : Flags = .{},
33
+ /// Specifies whether this atom is alive or has been garbage collected.
34
+ alive : bool = true ,
35
+
36
+ /// Specifies if the atom has been visited during garbage collection.
37
+ visited : bool = false ,
35
38
36
39
extra_index : u32 = 0 ,
37
40
38
41
pub const Alignment = @import ("../../InternPool.zig" ).Alignment ;
39
42
40
- pub fn name (self : Atom , elf_file : * Elf ) []const u8 {
43
+ pub fn name (self : Atom , elf_file : * Elf ) [: 0 ]const u8 {
41
44
const file_ptr = self .file (elf_file ).? ;
42
45
return switch (file_ptr ) {
43
46
inline else = > | x | x .getString (self .name_offset ),
44
47
};
45
48
}
46
49
47
50
pub fn address (self : Atom , elf_file : * Elf ) i64 {
48
- const shndx = self .outputShndx () orelse return self .value ;
49
- const shdr = elf_file .shdrs .items [shndx ];
51
+ const shdr = elf_file .shdrs .items [self .output_section_index ];
50
52
return @as (i64 , @intCast (shdr .sh_addr )) + self .value ;
51
53
}
52
54
@@ -55,7 +57,7 @@ pub fn debugTombstoneValue(self: Atom, target: Symbol, elf_file: *Elf) ?u64 {
55
57
if (msub .alive ) return null ;
56
58
}
57
59
if (target .atom (elf_file )) | atom_ptr | {
58
- if (atom_ptr .flags . alive ) return null ;
60
+ if (atom_ptr .alive ) return null ;
59
61
}
60
62
const atom_name = self .name (elf_file );
61
63
if (! mem .startsWith (u8 , atom_name , ".debug" )) return null ;
@@ -67,8 +69,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
67
69
}
68
70
69
71
pub fn thunk (self : Atom , elf_file : * Elf ) * Thunk {
70
- assert (self .flags .thunk );
71
- const extras = self .extra (elf_file ).? ;
72
+ const extras = self .extra (elf_file );
72
73
return elf_file .thunk (extras .thunk );
73
74
}
74
75
@@ -85,11 +86,6 @@ pub fn relocsShndx(self: Atom) ?u32 {
85
86
return self .relocs_section_index ;
86
87
}
87
88
88
- pub fn outputShndx (self : Atom ) ? u32 {
89
- if (self .output_section_index == 0 ) return null ;
90
- return self .output_section_index ;
91
- }
92
-
93
89
pub fn priority (self : Atom , elf_file : * Elf ) u64 {
94
90
const index = self .file (elf_file ).? .index ();
95
91
return (@as (u64 , @intCast (index )) << 32 ) | @as (u64 , @intCast (self .input_section_index ));
@@ -99,16 +95,18 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 {
99
95
/// File offset relocation happens transparently, so it is not included in
100
96
/// this calculation.
101
97
pub fn capacity (self : Atom , elf_file : * Elf ) u64 {
102
- const next_addr = if (elf_file .atom (self .next_index )) | next |
98
+ const zo = elf_file .zigObjectPtr ().? ;
99
+ const next_addr = if (zo .atom (self .next_index )) | next |
103
100
next .address (elf_file )
104
101
else
105
102
std .math .maxInt (u32 );
106
103
return @intCast (next_addr - self .address (elf_file ));
107
104
}
108
105
109
106
pub fn freeListEligible (self : Atom , elf_file : * Elf ) bool {
107
+ const zo = elf_file .zigObjectPtr ().? ;
110
108
// No need to keep a free list node for the last block.
111
- const next = elf_file .atom (self .next_index ) orelse return false ;
109
+ const next = zo .atom (self .next_index ) orelse return false ;
112
110
const cap : u64 = @intCast (next .address (elf_file ) - self .address (elf_file ));
113
111
const ideal_cap = Elf .padToIdeal (self .size );
114
112
if (cap <= ideal_cap ) return false ;
@@ -117,8 +115,9 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
117
115
}
118
116
119
117
pub fn allocate (self : * Atom , elf_file : * Elf ) ! void {
120
- const shdr = & elf_file .shdrs .items [self .outputShndx ().? ];
121
- const meta = elf_file .last_atom_and_free_list_table .getPtr (self .outputShndx ().? ).? ;
118
+ const zo = elf_file .zigObjectPtr ().? ;
119
+ const shdr = & elf_file .shdrs .items [self .output_section_index ];
120
+ const meta = elf_file .last_atom_and_free_list_table .getPtr (self .output_section_index ).? ;
122
121
const free_list = & meta .free_list ;
123
122
const last_atom_index = & meta .last_atom_index ;
124
123
const new_atom_ideal_capacity = Elf .padToIdeal (self .size );
@@ -137,7 +136,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
137
136
var i : usize = if (elf_file .base .child_pid == null ) 0 else free_list .items .len ;
138
137
while (i < free_list .items .len ) {
139
138
const big_atom_index = free_list .items [i ];
140
- const big_atom = elf_file .atom (big_atom_index ).? ;
139
+ const big_atom = zo .atom (big_atom_index ).? ;
141
140
// We now have a pointer to a live atom that has too much capacity.
142
141
// Is it enough that we could fit this new atom?
143
142
const cap = big_atom .capacity (elf_file );
@@ -169,7 +168,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
169
168
free_list_removal = i ;
170
169
}
171
170
break :blk @intCast (new_start_vaddr );
172
- } else if (elf_file .atom (last_atom_index .* )) | last | {
171
+ } else if (zo .atom (last_atom_index .* )) | last | {
173
172
const ideal_capacity = Elf .padToIdeal (last .size );
174
173
const ideal_capacity_end_vaddr = @as (u64 , @intCast (last .value )) + ideal_capacity ;
175
174
const new_start_vaddr = self .alignment .forward (ideal_capacity_end_vaddr );
@@ -189,12 +188,12 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
189
188
});
190
189
191
190
const expand_section = if (atom_placement ) | placement_index |
192
- elf_file .atom (placement_index ).? .next_index == 0
191
+ zo .atom (placement_index ).? .next_index == 0
193
192
else
194
193
true ;
195
194
if (expand_section ) {
196
195
const needed_size : u64 = @intCast (self .value + @as (i64 , @intCast (self .size )));
197
- try elf_file .growAllocSection (self .outputShndx () .? , needed_size );
196
+ try elf_file .growAllocSection (self .output_section_index , needed_size );
198
197
last_atom_index .* = self .atom_index ;
199
198
200
199
const zig_object = elf_file .zigObjectPtr ().? ;
@@ -214,15 +213,15 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
214
213
// This function can also reallocate an atom.
215
214
// In this case we need to "unplug" it from its previous location before
216
215
// plugging it in to its new location.
217
- if (elf_file .atom (self .prev_index )) | prev | {
216
+ if (zo .atom (self .prev_index )) | prev | {
218
217
prev .next_index = self .next_index ;
219
218
}
220
- if (elf_file .atom (self .next_index )) | next | {
219
+ if (zo .atom (self .next_index )) | next | {
221
220
next .prev_index = self .prev_index ;
222
221
}
223
222
224
223
if (atom_placement ) | big_atom_index | {
225
- const big_atom = elf_file .atom (big_atom_index ).? ;
224
+ const big_atom = zo .atom (big_atom_index ).? ;
226
225
self .prev_index = big_atom_index ;
227
226
self .next_index = big_atom .next_index ;
228
227
big_atom .next_index = self .atom_index ;
@@ -234,7 +233,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
234
233
_ = free_list .swapRemove (i );
235
234
}
236
235
237
- self .flags . alive = true ;
236
+ self .alive = true ;
238
237
}
239
238
240
239
pub fn shrink (self : * Atom , elf_file : * Elf ) void {
@@ -250,9 +249,10 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void {
250
249
pub fn free (self : * Atom , elf_file : * Elf ) void {
251
250
log .debug ("freeAtom {d} ({s})" , .{ self .atom_index , self .name (elf_file ) });
252
251
252
+ const zo = elf_file .zigObjectPtr ().? ;
253
253
const comp = elf_file .base .comp ;
254
254
const gpa = comp .gpa ;
255
- const shndx = self .outputShndx () .? ;
255
+ const shndx = self .output_section_index ;
256
256
const meta = elf_file .last_atom_and_free_list_table .getPtr (shndx ).? ;
257
257
const free_list = & meta .free_list ;
258
258
const last_atom_index = & meta .last_atom_index ;
@@ -272,9 +272,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
272
272
}
273
273
}
274
274
275
- if (elf_file .atom (last_atom_index .* )) | last_atom | {
275
+ if (zo .atom (last_atom_index .* )) | last_atom | {
276
276
if (last_atom .atom_index == self .atom_index ) {
277
- if (elf_file .atom (self .prev_index )) | _ | {
277
+ if (zo .atom (self .prev_index )) | _ | {
278
278
// TODO shrink the section size here
279
279
last_atom_index .* = self .prev_index ;
280
280
} else {
@@ -283,7 +283,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
283
283
}
284
284
}
285
285
286
- if (elf_file .atom (self .prev_index )) | prev | {
286
+ if (zo .atom (self .prev_index )) | prev | {
287
287
prev .next_index = self .next_index ;
288
288
if (! already_have_free_list_node and prev .* .freeListEligible (elf_file )) {
289
289
// The free list is heuristics, it doesn't have to be perfect, so we can
@@ -294,7 +294,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
294
294
self .prev_index = 0 ;
295
295
}
296
296
297
- if (elf_file .atom (self .next_index )) | next | {
297
+ if (zo .atom (self .next_index )) | next | {
298
298
next .prev_index = self .prev_index ;
299
299
} else {
300
300
self .next_index = 0 ;
@@ -313,7 +313,7 @@ pub fn relocs(self: Atom, elf_file: *Elf) []const elf.Elf64_Rela {
313
313
switch (self .file (elf_file ).? ) {
314
314
.zig_object = > | x | return x .relocs .items [shndx ].items ,
315
315
.object = > | x | {
316
- const extras = self .extra (elf_file ).? ;
316
+ const extras = self .extra (elf_file );
317
317
return x .relocs .items [extras .rel_index .. ][0.. extras .rel_count ];
318
318
},
319
319
else = > unreachable ,
@@ -337,12 +337,12 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
337
337
var r_addend = rel .r_addend ;
338
338
var r_sym : u32 = 0 ;
339
339
switch (target .type (elf_file )) {
340
- elf .STT_SECTION = > if (target .mergeSubsection (elf_file )) | msub | {
341
- r_addend += @intCast (target .address (.{}, elf_file ));
342
- r_sym = elf_file .sectionSymbolOutputSymtabIndex (msub .mergeSection (elf_file ).output_section_index );
343
- } else {
340
+ elf .STT_SECTION = > {
344
341
r_addend += @intCast (target .address (.{}, elf_file ));
345
- r_sym = elf_file .sectionSymbolOutputSymtabIndex (target .outputShndx ().? );
342
+ r_sym = if (target .outputShndx (elf_file )) | osec |
343
+ elf_file .sectionSymbolOutputSymtabIndex (osec )
344
+ else
345
+ 0 ;
346
346
},
347
347
else = > {
348
348
r_sym = target .outputSymtabIndex (elf_file ) orelse 0 ;
@@ -366,10 +366,12 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
366
366
}
367
367
368
368
pub fn fdes (self : Atom , elf_file : * Elf ) []Fde {
369
- if (! self .flags .fde ) return &[0 ]Fde {};
370
- const extras = self .extra (elf_file ).? ;
371
- const object = self .file (elf_file ).? .object ;
372
- return object .fdes .items [extras .fde_start .. ][0.. extras .fde_count ];
369
+ const extras = self .extra (elf_file );
370
+ return switch (self .file (elf_file ).? ) {
371
+ .shared_object = > unreachable ,
372
+ .linker_defined , .zig_object = > &[0 ]Fde {},
373
+ .object = > | x | x .fdes .items [extras .fde_start .. ][0.. extras .fde_count ],
374
+ };
373
375
}
374
376
375
377
pub fn markFdesDead (self : Atom , elf_file : * Elf ) void {
@@ -712,9 +714,9 @@ fn reportUndefined(
712
714
{
713
715
const gop = try undefs .getOrPut (sym_index );
714
716
if (! gop .found_existing ) {
715
- gop .value_ptr .* = std .ArrayList (Atom . Index ).init (gpa );
717
+ gop .value_ptr .* = std .ArrayList (Elf . Ref ).init (gpa );
716
718
}
717
- try gop .value_ptr .append (self .atom_index );
719
+ try gop .value_ptr .append (.{ . index = self .atom_index , . file = self . file_index } );
718
720
return true ;
719
721
}
720
722
@@ -1001,25 +1003,23 @@ const AddExtraOpts = struct {
1001
1003
rel_count : ? u32 = null ,
1002
1004
};
1003
1005
1004
- pub fn addExtra (atom : * Atom , opts : AddExtraOpts , elf_file : * Elf ) ! void {
1005
- if (atom .extra (elf_file ) == null ) {
1006
- atom .extra_index = try elf_file .addAtomExtra (.{});
1007
- }
1008
- var extras = atom .extra (elf_file ).? ;
1006
+ pub fn addExtra (atom : * Atom , opts : AddExtraOpts , elf_file : * Elf ) void {
1007
+ const file_ptr = atom .file (elf_file ).? ;
1008
+ var extras = file_ptr .atomExtra (atom .extra_index );
1009
1009
inline for (@typeInfo (@TypeOf (opts )).Struct .fields ) | field | {
1010
1010
if (@field (opts , field .name )) | x | {
1011
1011
@field (extras , field .name ) = x ;
1012
1012
}
1013
1013
}
1014
- atom . setExtra ( extras , elf_file );
1014
+ file_ptr . setAtomExtra ( atom . extra_index , extras );
1015
1015
}
1016
1016
1017
- pub inline fn extra (atom : Atom , elf_file : * Elf ) ? Extra {
1018
- return elf_file .atomExtra (atom .extra_index );
1017
+ pub inline fn extra (atom : Atom , elf_file : * Elf ) Extra {
1018
+ return atom . file ( elf_file ) .? .atomExtra (atom .extra_index );
1019
1019
}
1020
1020
1021
1021
pub inline fn setExtra (atom : Atom , extras : Extra , elf_file : * Elf ) void {
1022
- elf_file .setAtomExtra (atom .extra_index , extras );
1022
+ atom . file ( elf_file ) .? .setAtomExtra (atom .extra_index , extras );
1023
1023
}
1024
1024
1025
1025
pub fn format (
@@ -1061,37 +1061,23 @@ fn format2(
1061
1061
atom .atom_index , atom .name (elf_file ), atom .address (elf_file ),
1062
1062
atom .output_section_index , atom .alignment , atom .size ,
1063
1063
});
1064
- if (atom .flags . fde ) {
1064
+ if (atom .fdes ( elf_file ). len > 0 ) {
1065
1065
try writer .writeAll (" : fdes{ " );
1066
- const extras = atom .extra (elf_file ).? ;
1066
+ const extras = atom .extra (elf_file );
1067
1067
for (atom .fdes (elf_file ), extras .fde_start .. ) | fde , i | {
1068
1068
try writer .print ("{d}" , .{i });
1069
1069
if (! fde .alive ) try writer .writeAll ("([*])" );
1070
1070
if (i - extras .fde_start < extras .fde_count - 1 ) try writer .writeAll (", " );
1071
1071
}
1072
1072
try writer .writeAll (" }" );
1073
1073
}
1074
- if (! atom .flags . alive ) {
1074
+ if (! atom .alive ) {
1075
1075
try writer .writeAll (" : [*]" );
1076
1076
}
1077
1077
}
1078
1078
1079
1079
pub const Index = u32 ;
1080
1080
1081
- pub const Flags = packed struct {
1082
- /// Specifies whether this atom is alive or has been garbage collected.
1083
- alive : bool = true ,
1084
-
1085
- /// Specifies if the atom has been visited during garbage collection.
1086
- visited : bool = false ,
1087
-
1088
- /// Whether this atom has a range extension thunk.
1089
- thunk : bool = false ,
1090
-
1091
- /// Whether this atom has FDE records.
1092
- fde : bool = false ,
1093
- };
1094
-
1095
1081
const x86_64 = struct {
1096
1082
fn scanReloc (
1097
1083
atom : Atom ,
0 commit comments