1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-11 05:46:58 +03:00

[Mach-O] Handle .bss

This commit is contained in:
Rui Ueyama 2021-10-29 10:45:12 +09:00
parent 16d904a198
commit c227286dd5
5 changed files with 65 additions and 14 deletions

View File

@ -13,6 +13,7 @@ std::ostream &operator<<(std::ostream &out, const InputSection &sec) {
InputSection::InputSection(Context &ctx, ObjectFile &file, const MachSection &hdr)
: file(file), hdr(hdr),
osec(*OutputSection::get_instance(ctx, hdr.get_segname(), hdr.get_sectname())) {
if (hdr.type != S_ZEROFILL)
contents = file.mf->get_contents().substr(hdr.offset, hdr.size);
subsections.push_back({*this, 0, (u32)contents.size(), (u32)hdr.addr});
}

View File

@ -62,6 +62,9 @@ static void create_synthetic_chunks(Context &ctx) {
ctx.data_seg.chunks.push_back(&ctx.lazy_symbol_ptr);
ctx.data_seg.chunks.push_back(ctx.data);
if (!ctx.bss->members.empty())
ctx.data_seg.chunks.push_back(ctx.bss);
ctx.linkedit_seg.chunks.push_back(&ctx.rebase);
ctx.linkedit_seg.chunks.push_back(&ctx.bind);
ctx.linkedit_seg.chunks.push_back(&ctx.lazy_bind);

View File

@ -127,6 +127,7 @@ std::ostream &operator<<(std::ostream &out, const InputSection &sec);
class Subsection {
public:
std::string_view get_contents() {
assert(isec.hdr.type != S_ZEROFILL);
return isec.contents.substr(input_offset, input_size);
}
@ -583,8 +584,11 @@ struct Context {
Context() {
text = OutputSection::get_instance(*this, "__TEXT", "__text");
data = OutputSection::get_instance(*this, "__DATA", "__data");
bss = OutputSection::get_instance(*this, "__DATA", "__bss");
cstring = OutputSection::get_instance(*this, "__TEXT", "__cstring");
common = OutputSection::get_instance(*this, "__TEXT", "__common");
bss->hdr.type = S_ZEROFILL;
cstring->hdr.type = S_CSTRING_LITERALS;
}
@ -660,6 +664,7 @@ struct Context {
OutputSection *text = nullptr;
OutputSection *data = nullptr;
OutputSection *bss = nullptr;
OutputSection *cstring = nullptr;
OutputSection *common = nullptr;

View File

@ -292,11 +292,13 @@ void OutputSection::copy_buf(Context &ctx) {
u8 *buf = ctx.buf + hdr.offset;
for (Subsection *subsec : members) {
if (subsec->isec.hdr.type != S_ZEROFILL) {
std::string_view data = subsec->get_contents();
memcpy(buf + subsec->output_offset, data.data(), data.size());
subsec->apply_reloc(ctx, buf + subsec->output_offset);
}
}
}
OutputSegment::OutputSegment(std::string_view name, u32 prot, u32 flags) {
cmd.cmd = LC_SEGMENT_64;
@ -310,19 +312,36 @@ void OutputSegment::set_offset(Context &ctx, i64 fileoff, u64 vmaddr) {
cmd.fileoff = fileoff;
cmd.vmaddr = vmaddr;
i64 offset = 0;
i64 i = 0;
for (Chunk *sec : chunks) {
offset = align_to(offset, 1 << sec->hdr.p2align);
sec->hdr.addr = vmaddr + offset;
sec->hdr.offset = fileoff + offset;
sec->compute_size(ctx);
offset += sec->hdr.size;
while (i < chunks.size() && chunks[i]->hdr.type != S_ZEROFILL) {
Chunk &sec = *chunks[i++];
fileoff = align_to(fileoff, 1 << sec.hdr.p2align);
vmaddr = align_to(vmaddr, 1 << sec.hdr.p2align);
sec.hdr.offset = fileoff;
sec.hdr.addr = vmaddr;
sec.compute_size(ctx);
fileoff += sec.hdr.size;
vmaddr += sec.hdr.size;
}
cmd.vmsize = align_to(offset, PAGE_SIZE);
cmd.filesize =
(this == ctx.segments.back()) ? offset : align_to(offset, PAGE_SIZE);
while (i < chunks.size()) {
Chunk &sec = *chunks[i++];
assert(sec.hdr.type == S_ZEROFILL);
vmaddr = align_to(vmaddr, 1 << sec.hdr.p2align);
sec.hdr.addr = vmaddr;
sec.compute_size(ctx);
vmaddr += sec.hdr.size;
}
cmd.vmsize = align_to(vmaddr - cmd.vmaddr, PAGE_SIZE);
if (this == ctx.segments.back())
cmd.filesize = fileoff - cmd.fileoff;
else
cmd.filesize = align_to(fileoff - cmd.fileoff, PAGE_SIZE);
}
void OutputSegment::copy_buf(Context &ctx) {

23
test/macho/bss.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
set -e
cd $(dirname $0)
mold=`pwd`/../../ld64.mold
echo -n "Testing $(basename -s .sh $0) ... "
t=$(pwd)/../../out/test/macho/$(basename -s .sh $0)
mkdir -p $t
cat <<EOF | cc -o $t/a.o -c -xc -
#include <stdio.h>
static int foo[100];
int main() {
foo[1] = 5;
printf("%d %d %p\n", foo[0], foo[1], foo);
}
EOF
clang -fuse-ld=$mold -o $t/exe $t/a.o
$t/exe | grep -q '^0 5 '
echo OK