1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-11 13:06:59 +03:00

Compare commits

...

2 Commits

Author SHA1 Message Date
Rui Ueyama
49fc7da32e Refactor 2023-08-01 00:39:25 +09:00
Rui Ueyama
dd56734fda Fix symbol table for very large section indices 2023-07-31 19:38:04 +09:00
7 changed files with 65 additions and 58 deletions

View File

@ -394,30 +394,36 @@ inline i64 write_uleb(u8 *buf, u64 val) {
return i;
}
inline u64 read_uleb(u8 *&buf) {
inline u64 read_uleb(u8 **buf) {
u64 val = 0;
u8 shift = 0;
u8 byte;
do {
byte = *buf++;
byte = *(*buf)++;
val |= (byte & 0x7f) << shift;
shift += 7;
} while (byte & 0x80);
return val;
}
inline u64 read_uleb(u8 const*&buf) {
return read_uleb(const_cast<u8 *&>(buf));
inline u64 read_uleb(u8 *buf) {
u8 *tmp = buf;
return read_uleb(&tmp);
}
inline u64 read_uleb(std::string_view &str) {
u8 *start = (u8 *)&str[0];
inline u64 read_uleb(std::string_view *str) {
u8 *start = (u8 *)str->data();
u8 *ptr = start;
u64 val = read_uleb(ptr);
str = str.substr(ptr - start);
u64 val = read_uleb(&ptr);
*str = str->substr(ptr - start);
return val;
}
inline u64 read_uleb(std::string_view str) {
std::string_view tmp = str;
return read_uleb(&tmp);
}
inline i64 uleb_size(u64 val) {
#if __GNUC__
#pragma GCC unroll 8

View File

@ -530,12 +530,9 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
case R_RISCV_SET_ULEB128:
overwrite_uleb(loc, S + A);
break;
case R_RISCV_SUB_ULEB128: {
u8 *p = loc;
u64 val = read_uleb(p);
overwrite_uleb(loc, val - S - A);
case R_RISCV_SUB_ULEB128:
overwrite_uleb(loc, read_uleb(loc) - S - A);
break;
}
default:
unreachable();
}
@ -613,12 +610,9 @@ void InputSection<E>::apply_reloc_nonalloc(Context<E> &ctx, u8 *base) {
case R_RISCV_SET_ULEB128:
overwrite_uleb(loc, S + A);
break;
case R_RISCV_SUB_ULEB128: {
u8 *p = loc;
u64 val = read_uleb(p);
overwrite_uleb(loc, val - S - A);
case R_RISCV_SUB_ULEB128:
overwrite_uleb(loc, read_uleb(loc) - S - A);
break;
}
default:
Fatal(ctx) << *this << ": invalid relocation for non-allocated sections: "
<< rel;

View File

@ -216,7 +216,7 @@ find_compunit(Context<E> &ctx, ObjectFile<E> &file, i64 offset) {
<< dwarf_version;
}
u32 abbrev_code = read_uleb(cu);
u32 abbrev_code = read_uleb(&cu);
// Find a .debug_abbrev record corresponding to the .debug_info record.
// We assume the .debug_info record at a given offset is of
@ -224,14 +224,14 @@ find_compunit(Context<E> &ctx, ObjectFile<E> &file, i64 offset) {
u8 *abbrev = get_buffer(ctx, ctx.debug_abbrev) + abbrev_offset;
for (;;) {
u32 code = read_uleb(abbrev);
u32 code = read_uleb(&abbrev);
if (code == 0)
Fatal(ctx) << file << ": --gdb-index: .debug_abbrev does not contain"
<< " a record for the first .debug_info record";
if (code == abbrev_code) {
// Found a record
u64 abbrev_tag = read_uleb(abbrev);
u64 abbrev_tag = read_uleb(&abbrev);
if (abbrev_tag != DW_TAG_compile_unit && abbrev_tag != DW_TAG_skeleton_unit)
Fatal(ctx) << file << ": --gdb-index: the first entry's tag is not"
<< " DW_TAG_compile_unit/DW_TAG_skeleton_unit but 0x"
@ -240,15 +240,15 @@ find_compunit(Context<E> &ctx, ObjectFile<E> &file, i64 offset) {
}
// Skip an uninteresting record
read_uleb(abbrev); // tag
read_uleb(&abbrev); // tag
abbrev++; // has_children byte
for (;;) {
u64 name = read_uleb(abbrev);
u64 form = read_uleb(abbrev);
u64 name = read_uleb(&abbrev);
u64 form = read_uleb(&abbrev);
if (name == 0 && form == 0)
break;
if (form == DW_FORM_implicit_const)
read_uleb(abbrev);
read_uleb(&abbrev);
}
}
@ -348,7 +348,7 @@ u64 DebugInfoReader<E>::read(u64 form) {
case DW_FORM_ref_udata:
case DW_FORM_loclistx:
case DW_FORM_rnglistx:
return read_uleb(cu);
return read_uleb(&cu);
case DW_FORM_string:
cu += strlen((char *)cu) + 1;
return 0;
@ -391,19 +391,19 @@ read_rnglist_range(Context<E> &ctx, ObjectFile<E> &file, u8 *rnglist,
case DW_RLE_end_of_list:
return vec;
case DW_RLE_base_addressx:
base = addrx[read_uleb(rnglist)];
base = addrx[read_uleb(&rnglist)];
break;
case DW_RLE_startx_endx:
vec.push_back(addrx[read_uleb(rnglist)]);
vec.push_back(addrx[read_uleb(rnglist)]);
vec.push_back(addrx[read_uleb(&rnglist)]);
vec.push_back(addrx[read_uleb(&rnglist)]);
break;
case DW_RLE_startx_length:
vec.push_back(addrx[read_uleb(rnglist)]);
vec.push_back(vec.back() + read_uleb(rnglist));
vec.push_back(addrx[read_uleb(&rnglist)]);
vec.push_back(vec.back() + read_uleb(&rnglist));
break;
case DW_RLE_offset_pair:
vec.push_back(base + read_uleb(rnglist));
vec.push_back(base + read_uleb(rnglist));
vec.push_back(base + read_uleb(&rnglist));
vec.push_back(base + read_uleb(&rnglist));
break;
case DW_RLE_base_address:
base = *(Word<E> *)rnglist;
@ -418,7 +418,7 @@ read_rnglist_range(Context<E> &ctx, ObjectFile<E> &file, u8 *rnglist,
case DW_RLE_start_length:
vec.push_back(*(Word<E> *)rnglist);
rnglist += sizeof(Word<E>);
vec.push_back(vec.back() + read_uleb(rnglist));
vec.push_back(vec.back() + read_uleb(&rnglist));
break;
}
}
@ -455,8 +455,8 @@ read_address_areas(Context<E> &ctx, ObjectFile<E> &file, i64 offset) {
// Read all interesting debug records.
for (;;) {
u64 name = read_uleb(abbrev);
u64 form = read_uleb(abbrev);
u64 name = read_uleb(&abbrev);
u64 form = read_uleb(&abbrev);
if (name == 0 && form == 0)
break;

View File

@ -55,9 +55,9 @@ enum : u32 {
enum : u32 {
SHN_UNDEF = 0,
SHN_LORESERVE = 0xff00,
SHN_ABS = 0xfff1,
SHN_COMMON = 0xfff2,
SHN_LORESERVE = 0xff00,
SHN_XINDEX = 0xffff,
};

View File

@ -177,17 +177,17 @@ const char *begin = data.data();
p = p.substr(5); // skip the tag and the sub-sub-section size
while (!p.empty()) {
i64 tag = read_uleb(p);
i64 tag = read_uleb(&p);
switch (tag) {
case ELF_TAG_RISCV_STACK_ALIGN:
file.extra.stack_align = read_uleb(p);
file.extra.stack_align = read_uleb(&p);
break;
case ELF_TAG_RISCV_ARCH:
file.extra.arch = read_string(p);
break;
case ELF_TAG_RISCV_UNALIGNED_ACCESS:
file.extra.unaligned_access = read_uleb(p);
file.extra.unaligned_access = read_uleb(&p);
break;
default:
break;
@ -908,7 +908,7 @@ void ObjectFile<E>::mark_addrsig(Context<E> &ctx) {
u8 *end = cur + llvm_addrsig->contents.size();
while (cur != end) {
Symbol<E> &sym = *this->symbols[read_uleb(cur)];
Symbol<E> &sym = *this->symbols[read_uleb(&cur)];
if (sym.file == this)
if (InputSection<E> *isec = sym.get_input_section())
isec->address_significant = true;

View File

@ -655,6 +655,11 @@ void SymtabSection<E>::copy_buf(Context<E> &ctx) {
// Write the initial NUL byte to .strtab.
ctx.buf[ctx.strtab->shdr.sh_offset] = '\0';
if (ctx.symtab_shndx) {
ElfShdr<E> &shdr = ctx.symtab_shndx->shdr;
memset(ctx.buf + shdr.sh_offset, 0, shdr.sh_size);
}
// Create section symbols
for (Chunk<E> *chunk : ctx.chunks) {
if (chunk->shndx) {
@ -1606,12 +1611,12 @@ ElfSym<E> to_output_esym(Context<E> &ctx, Symbol<E> &sym, u32 st_name,
return SHN_UNDEF;
};
u32 shndx = 0;
i64 shndx = -1;
if (sym.has_copyrel) {
shndx = sym.is_copyrel_readonly ? ctx.copyrel_relro->shndx : ctx.copyrel->shndx;
esym.st_value = sym.get_addr(ctx);
} else if (sym.file->is_dso || sym.esym().is_undef()) {
shndx = SHN_UNDEF;
esym.st_shndx = SHN_UNDEF;
if (sym.is_canonical)
esym.st_value = sym.get_plt_addr(ctx);
} else if (Chunk<E> *osec = sym.get_output_section()) {
@ -1624,7 +1629,7 @@ ElfSym<E> to_output_esym(Context<E> &ctx, Symbol<E> &sym, u32 st_name,
esym.st_value = sym.get_addr(ctx);
} else if (!sym.get_input_section()) {
// Absolute symbol
shndx = SHN_ABS;
esym.st_shndx = SHN_ABS;
esym.st_value = sym.get_addr(ctx);
} else if (sym.get_type() == STT_TLS) {
shndx = get_st_shndx(sym);
@ -1640,17 +1645,12 @@ ElfSym<E> to_output_esym(Context<E> &ctx, Symbol<E> &sym, u32 st_name,
// or greater than SHN_LORESERVE (= 65280), the real index is stored
// to a SHT_SYMTAB_SHNDX section which contains a parallel array of
// the symbol table.
if (shn_xindex) {
*shn_xindex = shndx;
if (shndx == SHN_UNDEF || shndx == SHN_ABS || shndx == SHN_COMMON)
esym.st_shndx = shndx;
else
esym.st_shndx = SHN_XINDEX;
} else {
if (shndx >= SHN_LORESERVE && shndx != SHN_ABS && shndx != SHN_COMMON)
Fatal(ctx) << sym << ": internal error: output symbol index too large: "
<< shndx;
if (0 <= shndx && shndx < SHN_LORESERVE) {
esym.st_shndx = shndx;
} else if (SHN_LORESERVE <= shndx) {
assert(shn_xindex);
esym.st_shndx = SHN_XINDEX;
*shn_xindex = shndx;
}
return esym;

View File

@ -4,9 +4,16 @@
# OneTBB isn't tsan-clean
nm mold | grep -q '__tsan_init' && skip
seq 1 100000 | sed 's/.*/.section .data.\0,"aw"\n.globl x\0\nx\0: .word 0\n/g' | \
$CC -c -xassembler -o $t/a.o -
echo 'foo = 0x1000' > $t/a.s
seq 1 100000 | sed 's/.*/.section .data.\0,"aw"\n.globl x\0\nx\0: .word 0\n/g' >> $t/a.s
$CC -c -xassembler -o $t/a.o $t/a.s
./mold --relocatable -o $t/b.o $t/a.o
readelf -WS $t/b.o | grep -Fq .data.100000
readelf -Ws $t/b.o | grep -Fq 'GLOBAL DEFAULT 100000'
readelf -WS $t/b.o > $t/log1
grep -Fq .data.100000 $t/log1
readelf -Ws $t/b.o > $t/log2
grep -Fq 'GLOBAL DEFAULT 100000' $t/log2
grep -Fq 'ABS foo' $t/log2
! grep -Fq 'ABS x68966' $t/log2 || false