mirror of
https://github.com/ziglang/zig.git
synced 2025-12-27 00:23:22 +00:00
zld: fix incorrectly worked out section size
Also, add a solution to a degenerate case where on x86_64 a relocation refers to a cell in a section via section start address even though a symbol exists. In such case, make the section spawned symbol an alias of the actual symbol.
This commit is contained in:
parent
de30a704b1
commit
e17f12dd64
@ -431,29 +431,26 @@ const TextBlockParser = struct {
|
||||
else
|
||||
max_align;
|
||||
|
||||
const alias_only_indices = if (aliases.items.len > 0) blk: {
|
||||
var out = std.ArrayList(u32).init(self.allocator);
|
||||
try out.ensureTotalCapacity(aliases.items.len);
|
||||
const block = try self.allocator.create(TextBlock);
|
||||
errdefer self.allocator.destroy(block);
|
||||
|
||||
block.* = TextBlock.init(self.allocator);
|
||||
block.local_sym_index = senior_nlist.index;
|
||||
block.code = try self.allocator.dupe(u8, code);
|
||||
block.size = size;
|
||||
block.alignment = actual_align;
|
||||
|
||||
if (aliases.items.len > 0) {
|
||||
try block.aliases.ensureTotalCapacity(aliases.items.len);
|
||||
for (aliases.items) |alias| {
|
||||
out.appendAssumeCapacity(alias.index);
|
||||
block.aliases.appendAssumeCapacity(alias.index);
|
||||
|
||||
const sym = self.zld.locals.items[alias.index];
|
||||
const reg = &sym.payload.regular;
|
||||
reg.segment_id = self.match.seg;
|
||||
reg.section_id = self.match.sect;
|
||||
}
|
||||
break :blk out.toOwnedSlice();
|
||||
} else null;
|
||||
|
||||
const block = try self.allocator.create(TextBlock);
|
||||
errdefer self.allocator.destroy(block);
|
||||
|
||||
block.* = TextBlock.init(self.allocator);
|
||||
block.local_sym_index = senior_nlist.index;
|
||||
block.aliases = alias_only_indices;
|
||||
block.code = try self.allocator.dupe(u8, code);
|
||||
block.size = size;
|
||||
block.alignment = actual_align;
|
||||
}
|
||||
|
||||
const relocs = filterRelocs(self.relocs, start_addr, end_addr);
|
||||
if (relocs.len > 0) {
|
||||
@ -617,7 +614,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
|
||||
const tsect = &tseg.sections.items[match.sect];
|
||||
const new_alignment = math.max(tsect.@"align", block.alignment);
|
||||
const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
|
||||
const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2);
|
||||
const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size;
|
||||
tsect.size = new_size;
|
||||
tsect.@"align" = new_alignment;
|
||||
|
||||
@ -653,6 +650,19 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
|
||||
}
|
||||
}
|
||||
|
||||
if (reg.address == sect.addr) {
|
||||
if (self.sections_as_symbols.get(sect_id)) |alias| {
|
||||
// Add alias.
|
||||
const local_sym_index = @intCast(u32, zld.locals.items.len);
|
||||
const reg_alias = &alias.payload.regular;
|
||||
reg_alias.segment_id = match.seg;
|
||||
reg_alias.section_id = match.sect;
|
||||
reg_alias.local_sym_index = local_sym_index;
|
||||
try block.aliases.append(local_sym_index);
|
||||
try zld.locals.append(zld.allocator, alias);
|
||||
}
|
||||
}
|
||||
|
||||
// Update target section's metadata
|
||||
// TODO should we update segment's size here too?
|
||||
// How does it tie with incremental space allocs?
|
||||
@ -660,7 +670,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
|
||||
const tsect = &tseg.sections.items[match.sect];
|
||||
const new_alignment = math.max(tsect.@"align", block.alignment);
|
||||
const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
|
||||
const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2);
|
||||
const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size;
|
||||
tsect.size = new_size;
|
||||
tsect.@"align" = new_alignment;
|
||||
|
||||
@ -764,7 +774,7 @@ pub fn parseTextBlocks(self: *Object, zld: *Zld) !void {
|
||||
const tsect = &tseg.sections.items[match.sect];
|
||||
const new_alignment = math.max(tsect.@"align", block.alignment);
|
||||
const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
|
||||
const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2);
|
||||
const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size;
|
||||
tsect.size = new_size;
|
||||
tsect.@"align" = new_alignment;
|
||||
|
||||
|
||||
@ -125,7 +125,7 @@ pub const Output = struct {
|
||||
pub const TextBlock = struct {
|
||||
allocator: *Allocator,
|
||||
local_sym_index: u32,
|
||||
aliases: ?[]u32 = null,
|
||||
aliases: std.ArrayList(u32),
|
||||
references: std.AutoArrayHashMap(u32, void),
|
||||
contained: ?[]SymbolAtOffset = null,
|
||||
code: []u8,
|
||||
@ -146,6 +146,7 @@ pub const TextBlock = struct {
|
||||
return .{
|
||||
.allocator = allocator,
|
||||
.local_sym_index = undefined,
|
||||
.aliases = std.ArrayList(u32).init(allocator),
|
||||
.references = std.AutoArrayHashMap(u32, void).init(allocator),
|
||||
.code = undefined,
|
||||
.relocs = std.ArrayList(Relocation).init(allocator),
|
||||
@ -157,9 +158,7 @@ pub const TextBlock = struct {
|
||||
}
|
||||
|
||||
pub fn deinit(self: *TextBlock) void {
|
||||
if (self.aliases) |aliases| {
|
||||
self.allocator.free(aliases);
|
||||
}
|
||||
self.aliases.deinit();
|
||||
self.references.deinit();
|
||||
if (self.contained) |contained| {
|
||||
self.allocator.free(contained);
|
||||
@ -179,9 +178,9 @@ pub const TextBlock = struct {
|
||||
pub fn print_this(self: *const TextBlock, zld: *Zld) void {
|
||||
log.warn("TextBlock", .{});
|
||||
log.warn(" {}: {}", .{ self.local_sym_index, zld.locals.items[self.local_sym_index] });
|
||||
if (self.aliases) |aliases| {
|
||||
if (self.aliases.items.len > 0) {
|
||||
log.warn(" aliases:", .{});
|
||||
for (aliases) |index| {
|
||||
for (self.aliases.items) |index| {
|
||||
log.warn(" {}: {}", .{ index, zld.locals.items[index] });
|
||||
}
|
||||
}
|
||||
@ -1082,12 +1081,10 @@ fn allocateTextBlocks(self: *Zld) !void {
|
||||
});
|
||||
|
||||
// Update each alias (if any)
|
||||
if (block.aliases) |aliases| {
|
||||
for (aliases) |index| {
|
||||
const alias_sym = self.locals.items[index];
|
||||
assert(alias_sym.payload == .regular);
|
||||
alias_sym.payload.regular.address = base_addr;
|
||||
}
|
||||
for (block.aliases.items) |index| {
|
||||
const alias_sym = self.locals.items[index];
|
||||
assert(alias_sym.payload == .regular);
|
||||
alias_sym.payload.regular.address = base_addr;
|
||||
}
|
||||
|
||||
// Update each symbol contained within the TextBlock
|
||||
@ -1623,7 +1620,7 @@ fn resolveSymbols(self: *Zld) !void {
|
||||
const tsect = &tseg.sections.items[match.sect];
|
||||
const new_alignment = math.max(tsect.@"align", block.alignment);
|
||||
const new_alignment_pow_2 = try math.powi(u32, 2, new_alignment);
|
||||
const new_size = mem.alignForwardGeneric(u64, tsect.size + block.size, new_alignment_pow_2);
|
||||
const new_size = mem.alignForwardGeneric(u64, tsect.size, new_alignment_pow_2) + block.size;
|
||||
tsect.size = new_size;
|
||||
tsect.@"align" = new_alignment;
|
||||
|
||||
|
||||
@ -878,9 +878,9 @@ pub const Parser = struct {
|
||||
|
||||
if (rel.r_extern == 0) {
|
||||
const source_sym = self.zld.locals.items[self.block.local_sym_index].payload.regular;
|
||||
const source_addr = source_sym.address + parsed.offset + @intCast(u32, addend) + 4;
|
||||
const source_addr = source_sym.address + parsed.offset + 4;
|
||||
const target_sym = parsed.target.payload.regular;
|
||||
addend = @intCast(i64, source_addr) - @intCast(i64, target_sym.address);
|
||||
addend = @intCast(i64, source_addr) + addend - @intCast(i64, target_sym.address);
|
||||
}
|
||||
|
||||
parsed.payload = .{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user