11//! Represents a defined symbol.
22
33/// Allocated address value of this symbol.
4- value : u64 = 0 ,
4+ value : i64 = 0 ,
55
66/// Offset into the linker's string table.
77name_offset : u32 = 0 ,
@@ -14,7 +14,7 @@ file_index: File.Index = 0,
1414/// Use `atom` to get the pointer to the atom.
1515atom_index : Atom.Index = 0 ,
1616
17- /// Assigned output section index for this atom .
17+ /// Assigned output section index for this symbol .
1818output_section_index : u32 = 0 ,
1919
2020/// Index of the source symbol this symbol references.
@@ -33,7 +33,8 @@ extra_index: u32 = 0,
3333pub fn isAbs (symbol : Symbol , elf_file : * Elf ) bool {
3434 const file_ptr = symbol .file (elf_file ).? ;
3535 if (file_ptr == .shared_object ) return symbol .elfSym (elf_file ).st_shndx == elf .SHN_ABS ;
36- return ! symbol .flags .import and symbol .atom (elf_file ) == null and symbol .outputShndx () == null and
36+ return ! symbol .flags .import and symbol .atom (elf_file ) == null and
37+ symbol .mergeSubsection (elf_file ) == null and symbol .outputShndx () == null and
3738 file_ptr != .linker_defined ;
3839}
3940
@@ -70,6 +71,12 @@ pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {
7071 return elf_file .atom (symbol .atom_index );
7172}
7273
74+ pub fn mergeSubsection (symbol : Symbol , elf_file : * Elf ) ? * MergeSubsection {
75+ if (! symbol .flags .merge_subsection ) return null ;
76+ const extras = symbol .extra (elf_file ).? ;
77+ return elf_file .mergeSubsection (extras .subsection );
78+ }
79+
7380pub fn file (symbol : Symbol , elf_file : * Elf ) ? File {
7481 return elf_file .file (symbol .file_index );
7582}
@@ -92,7 +99,11 @@ pub fn symbolRank(symbol: Symbol, elf_file: *Elf) u32 {
9299 return file_ptr .symbolRank (sym , in_archive );
93100}
94101
95- pub fn address (symbol : Symbol , opts : struct { plt : bool = true }, elf_file : * Elf ) u64 {
102+ pub fn address (symbol : Symbol , opts : struct { plt : bool = true }, elf_file : * Elf ) i64 {
103+ if (symbol .mergeSubsection (elf_file )) | msub | {
104+ if (! msub .alive ) return 0 ;
105+ return msub .address (elf_file ) + symbol .value ;
106+ }
96107 if (symbol .flags .has_copy_rel ) {
97108 return symbol .copyRelAddress (elf_file );
98109 }
@@ -108,19 +119,23 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf
108119 if (! atom_ptr .flags .alive ) {
109120 if (mem .eql (u8 , atom_ptr .name (elf_file ), ".eh_frame" )) {
110121 const sym_name = symbol .name (elf_file );
122+ const sh_addr , const sh_size = blk : {
123+ const shndx = elf_file .eh_frame_section_index orelse break :blk .{ 0 , 0 };
124+ const shdr = elf_file .shdrs .items [shndx ];
125+ break :blk .{ shdr .sh_addr , shdr .sh_size };
126+ };
111127 if (mem .startsWith (u8 , sym_name , "__EH_FRAME_BEGIN__" ) or
112128 mem .startsWith (u8 , sym_name , "__EH_FRAME_LIST__" ) or
113129 mem .startsWith (u8 , sym_name , ".eh_frame_seg" ) or
114130 symbol .elfSym (elf_file ).st_type () == elf .STT_SECTION )
115131 {
116- return elf_file . shdrs . items [ elf_file . eh_frame_section_index .? ]. sh_addr ;
132+ return @intCast ( sh_addr ) ;
117133 }
118134
119135 if (mem .startsWith (u8 , sym_name , "__FRAME_END__" ) or
120136 mem .startsWith (u8 , sym_name , "__EH_FRAME_LIST_END__" ))
121137 {
122- const shdr = elf_file .shdrs .items [elf_file .eh_frame_section_index .? ];
123- return shdr .sh_addr + shdr .sh_size ;
138+ return @intCast (sh_addr + sh_size );
124139 }
125140
126141 // TODO I think we potentially should error here
@@ -143,65 +158,57 @@ pub fn outputSymtabIndex(symbol: Symbol, elf_file: *Elf) ?u32 {
143158 return if (symbol .isLocal (elf_file )) idx + symtab_ctx .ilocal else idx + symtab_ctx .iglobal ;
144159}
145160
146- pub fn setOutputSymtabIndex (symbol : * Symbol , index : u32 , elf_file : * Elf ) ! void {
147- if (symbol .extra (elf_file )) | extras | {
148- var new_extras = extras ;
149- new_extras .symtab = index ;
150- symbol .setExtra (new_extras , elf_file );
151- } else try symbol .addExtra (.{ .symtab = index }, elf_file );
152- }
153-
154- pub fn gotAddress (symbol : Symbol , elf_file : * Elf ) u64 {
161+ pub fn gotAddress (symbol : Symbol , elf_file : * Elf ) i64 {
155162 if (! symbol .flags .has_got ) return 0 ;
156163 const extras = symbol .extra (elf_file ).? ;
157164 const entry = elf_file .got .entries .items [extras .got ];
158165 return entry .address (elf_file );
159166}
160167
161- pub fn pltGotAddress (symbol : Symbol , elf_file : * Elf ) u64 {
168+ pub fn pltGotAddress (symbol : Symbol , elf_file : * Elf ) i64 {
162169 if (! (symbol .flags .has_plt and symbol .flags .has_got )) return 0 ;
163170 const extras = symbol .extra (elf_file ).? ;
164171 const shdr = elf_file .shdrs .items [elf_file .plt_got_section_index .? ];
165172 const cpu_arch = elf_file .getTarget ().cpu .arch ;
166- return shdr .sh_addr + extras .plt_got * PltGotSection .entrySize (cpu_arch );
173+ return @intCast ( shdr .sh_addr + extras .plt_got * PltGotSection .entrySize (cpu_arch ) );
167174}
168175
169- pub fn pltAddress (symbol : Symbol , elf_file : * Elf ) u64 {
176+ pub fn pltAddress (symbol : Symbol , elf_file : * Elf ) i64 {
170177 if (! symbol .flags .has_plt ) return 0 ;
171178 const extras = symbol .extra (elf_file ).? ;
172179 const shdr = elf_file .shdrs .items [elf_file .plt_section_index .? ];
173180 const cpu_arch = elf_file .getTarget ().cpu .arch ;
174- return shdr .sh_addr + extras .plt * PltSection .entrySize (cpu_arch ) + PltSection .preambleSize (cpu_arch );
181+ return @intCast ( shdr .sh_addr + extras .plt * PltSection .entrySize (cpu_arch ) + PltSection .preambleSize (cpu_arch ) );
175182}
176183
177- pub fn gotPltAddress (symbol : Symbol , elf_file : * Elf ) u64 {
184+ pub fn gotPltAddress (symbol : Symbol , elf_file : * Elf ) i64 {
178185 if (! symbol .flags .has_plt ) return 0 ;
179186 const extras = symbol .extra (elf_file ).? ;
180187 const shdr = elf_file .shdrs .items [elf_file .got_plt_section_index .? ];
181- return shdr .sh_addr + extras .plt * 8 + GotPltSection .preamble_size ;
188+ return @intCast ( shdr .sh_addr + extras .plt * 8 + GotPltSection .preamble_size ) ;
182189}
183190
184- pub fn copyRelAddress (symbol : Symbol , elf_file : * Elf ) u64 {
191+ pub fn copyRelAddress (symbol : Symbol , elf_file : * Elf ) i64 {
185192 if (! symbol .flags .has_copy_rel ) return 0 ;
186193 const shdr = elf_file .shdrs .items [elf_file .copy_rel_section_index .? ];
187- return shdr .sh_addr + symbol .value ;
194+ return @as ( i64 , @intCast ( shdr .sh_addr )) + symbol .value ;
188195}
189196
190- pub fn tlsGdAddress (symbol : Symbol , elf_file : * Elf ) u64 {
197+ pub fn tlsGdAddress (symbol : Symbol , elf_file : * Elf ) i64 {
191198 if (! symbol .flags .has_tlsgd ) return 0 ;
192199 const extras = symbol .extra (elf_file ).? ;
193200 const entry = elf_file .got .entries .items [extras .tlsgd ];
194201 return entry .address (elf_file );
195202}
196203
197- pub fn gotTpAddress (symbol : Symbol , elf_file : * Elf ) u64 {
204+ pub fn gotTpAddress (symbol : Symbol , elf_file : * Elf ) i64 {
198205 if (! symbol .flags .has_gottp ) return 0 ;
199206 const extras = symbol .extra (elf_file ).? ;
200207 const entry = elf_file .got .entries .items [extras .gottp ];
201208 return entry .address (elf_file );
202209}
203210
204- pub fn tlsDescAddress (symbol : Symbol , elf_file : * Elf ) u64 {
211+ pub fn tlsDescAddress (symbol : Symbol , elf_file : * Elf ) i64 {
205212 if (! symbol .flags .has_tlsdesc ) return 0 ;
206213 const extras = symbol .extra (elf_file ).? ;
207214 const entry = elf_file .got .entries .items [extras .tlsdesc ];
@@ -221,7 +228,7 @@ pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *E
221228 return .{ .found_existing = false , .index = index };
222229}
223230
224- pub fn zigGotAddress (symbol : Symbol , elf_file : * Elf ) u64 {
231+ pub fn zigGotAddress (symbol : Symbol , elf_file : * Elf ) i64 {
225232 if (! symbol .flags .has_zig_got ) return 0 ;
226233 const extras = symbol .extra (elf_file ).? ;
227234 return elf_file .zig_got .entryAddress (extras .zig_got , elf_file );
@@ -240,8 +247,31 @@ pub fn dsoAlignment(symbol: Symbol, elf_file: *Elf) !u64 {
240247 @min (alignment , try std .math .powi (u64 , 2 , @ctz (esym .st_value )));
241248}
242249
243- pub fn addExtra (symbol : * Symbol , extras : Extra , elf_file : * Elf ) ! void {
244- symbol .extra_index = try elf_file .addSymbolExtra (extras );
250+ const AddExtraOpts = struct {
251+ got : ? u32 = null ,
252+ plt : ? u32 = null ,
253+ plt_got : ? u32 = null ,
254+ dynamic : ? u32 = null ,
255+ symtab : ? u32 = null ,
256+ copy_rel : ? u32 = null ,
257+ tlsgd : ? u32 = null ,
258+ gottp : ? u32 = null ,
259+ tlsdesc : ? u32 = null ,
260+ zig_got : ? u32 = null ,
261+ subsection : ? u32 = null ,
262+ };
263+
264+ pub fn addExtra (symbol : * Symbol , opts : AddExtraOpts , elf_file : * Elf ) ! void {
265+ if (symbol .extra (elf_file ) == null ) {
266+ symbol .extra_index = try elf_file .addSymbolExtra (.{});
267+ }
268+ var extras = symbol .extra (elf_file ).? ;
269+ inline for (@typeInfo (@TypeOf (opts )).Struct .fields ) | field | {
270+ if (@field (opts , field .name )) | x | {
271+ @field (extras , field .name ) = x ;
272+ }
273+ }
274+ symbol .setExtra (extras , elf_file );
245275}
246276
247277pub fn extra (symbol : Symbol , elf_file : * Elf ) ? Extra {
@@ -266,6 +296,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
266296 if (symbol .flags .has_copy_rel ) break :blk @intCast (elf_file .copy_rel_section_index .? );
267297 if (file_ptr == .shared_object or esym .st_shndx == elf .SHN_UNDEF ) break :blk elf .SHN_UNDEF ;
268298 if (elf_file .base .isRelocatable () and esym .st_shndx == elf .SHN_COMMON ) break :blk elf .SHN_COMMON ;
299+ if (symbol .mergeSubsection (elf_file )) | msub | break :blk @intCast (msub .mergeSection (elf_file ).output_section_index );
269300 if (symbol .atom (elf_file ) == null and file_ptr != .linker_defined ) break :blk elf .SHN_ABS ;
270301 break :blk @intCast (symbol .outputShndx () orelse elf .SHN_UNDEF );
271302 };
@@ -284,7 +315,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
284315 out .st_info = (st_bind << 4 ) | st_type ;
285316 out .st_other = esym .st_other ;
286317 out .st_shndx = st_shndx ;
287- out .st_value = st_value ;
318+ out .st_value = @intCast ( st_value ) ;
288319 out .st_size = esym .st_size ;
289320}
290321
@@ -436,6 +467,9 @@ pub const Flags = packed struct {
436467 /// TODO this is really not needed if only we operated on esyms between
437468 /// codegen and ZigObject.
438469 is_tls : bool = false ,
470+
471+ /// Whether the symbol is a merge subsection.
472+ merge_subsection : bool = false ,
439473};
440474
441475pub const Extra = struct {
@@ -449,6 +483,7 @@ pub const Extra = struct {
449483 gottp : u32 = 0 ,
450484 tlsdesc : u32 = 0 ,
451485 zig_got : u32 = 0 ,
486+ subsection : u32 = 0 ,
452487};
453488
454489pub const Index = u32 ;
@@ -465,6 +500,7 @@ const File = @import("file.zig").File;
465500const GotSection = synthetic_sections .GotSection ;
466501const GotPltSection = synthetic_sections .GotPltSection ;
467502const LinkerDefined = @import ("LinkerDefined.zig" );
503+ const MergeSubsection = @import ("merge_section.zig" ).MergeSubsection ;
468504const Object = @import ("Object.zig" );
469505const PltSection = synthetic_sections .PltSection ;
470506const PltGotSection = synthetic_sections .PltGotSection ;
0 commit comments