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:
parent
16d904a198
commit
c227286dd5
@ -13,7 +13,8 @@ std::ostream &operator<<(std::ostream &out, const InputSection &sec) {
|
|||||||
InputSection::InputSection(Context &ctx, ObjectFile &file, const MachSection &hdr)
|
InputSection::InputSection(Context &ctx, ObjectFile &file, const MachSection &hdr)
|
||||||
: file(file), hdr(hdr),
|
: file(file), hdr(hdr),
|
||||||
osec(*OutputSection::get_instance(ctx, hdr.get_segname(), hdr.get_sectname())) {
|
osec(*OutputSection::get_instance(ctx, hdr.get_segname(), hdr.get_sectname())) {
|
||||||
contents = file.mf->get_contents().substr(hdr.offset, hdr.size);
|
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});
|
subsections.push_back({*this, 0, (u32)contents.size(), (u32)hdr.addr});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.lazy_symbol_ptr);
|
||||||
ctx.data_seg.chunks.push_back(ctx.data);
|
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.rebase);
|
||||||
ctx.linkedit_seg.chunks.push_back(&ctx.bind);
|
ctx.linkedit_seg.chunks.push_back(&ctx.bind);
|
||||||
ctx.linkedit_seg.chunks.push_back(&ctx.lazy_bind);
|
ctx.linkedit_seg.chunks.push_back(&ctx.lazy_bind);
|
||||||
|
@ -127,6 +127,7 @@ std::ostream &operator<<(std::ostream &out, const InputSection &sec);
|
|||||||
class Subsection {
|
class Subsection {
|
||||||
public:
|
public:
|
||||||
std::string_view get_contents() {
|
std::string_view get_contents() {
|
||||||
|
assert(isec.hdr.type != S_ZEROFILL);
|
||||||
return isec.contents.substr(input_offset, input_size);
|
return isec.contents.substr(input_offset, input_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,8 +584,11 @@ struct Context {
|
|||||||
Context() {
|
Context() {
|
||||||
text = OutputSection::get_instance(*this, "__TEXT", "__text");
|
text = OutputSection::get_instance(*this, "__TEXT", "__text");
|
||||||
data = OutputSection::get_instance(*this, "__DATA", "__data");
|
data = OutputSection::get_instance(*this, "__DATA", "__data");
|
||||||
|
bss = OutputSection::get_instance(*this, "__DATA", "__bss");
|
||||||
cstring = OutputSection::get_instance(*this, "__TEXT", "__cstring");
|
cstring = OutputSection::get_instance(*this, "__TEXT", "__cstring");
|
||||||
common = OutputSection::get_instance(*this, "__TEXT", "__common");
|
common = OutputSection::get_instance(*this, "__TEXT", "__common");
|
||||||
|
|
||||||
|
bss->hdr.type = S_ZEROFILL;
|
||||||
cstring->hdr.type = S_CSTRING_LITERALS;
|
cstring->hdr.type = S_CSTRING_LITERALS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,6 +664,7 @@ struct Context {
|
|||||||
|
|
||||||
OutputSection *text = nullptr;
|
OutputSection *text = nullptr;
|
||||||
OutputSection *data = nullptr;
|
OutputSection *data = nullptr;
|
||||||
|
OutputSection *bss = nullptr;
|
||||||
OutputSection *cstring = nullptr;
|
OutputSection *cstring = nullptr;
|
||||||
OutputSection *common = nullptr;
|
OutputSection *common = nullptr;
|
||||||
|
|
||||||
|
@ -292,9 +292,11 @@ void OutputSection::copy_buf(Context &ctx) {
|
|||||||
u8 *buf = ctx.buf + hdr.offset;
|
u8 *buf = ctx.buf + hdr.offset;
|
||||||
|
|
||||||
for (Subsection *subsec : members) {
|
for (Subsection *subsec : members) {
|
||||||
std::string_view data = subsec->get_contents();
|
if (subsec->isec.hdr.type != S_ZEROFILL) {
|
||||||
memcpy(buf + subsec->output_offset, data.data(), data.size());
|
std::string_view data = subsec->get_contents();
|
||||||
subsec->apply_reloc(ctx, buf + subsec->output_offset);
|
memcpy(buf + subsec->output_offset, data.data(), data.size());
|
||||||
|
subsec->apply_reloc(ctx, buf + subsec->output_offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,19 +312,36 @@ void OutputSegment::set_offset(Context &ctx, i64 fileoff, u64 vmaddr) {
|
|||||||
cmd.fileoff = fileoff;
|
cmd.fileoff = fileoff;
|
||||||
cmd.vmaddr = vmaddr;
|
cmd.vmaddr = vmaddr;
|
||||||
|
|
||||||
i64 offset = 0;
|
i64 i = 0;
|
||||||
|
|
||||||
for (Chunk *sec : chunks) {
|
while (i < chunks.size() && chunks[i]->hdr.type != S_ZEROFILL) {
|
||||||
offset = align_to(offset, 1 << sec->hdr.p2align);
|
Chunk &sec = *chunks[i++];
|
||||||
sec->hdr.addr = vmaddr + offset;
|
fileoff = align_to(fileoff, 1 << sec.hdr.p2align);
|
||||||
sec->hdr.offset = fileoff + offset;
|
vmaddr = align_to(vmaddr, 1 << sec.hdr.p2align);
|
||||||
sec->compute_size(ctx);
|
|
||||||
offset += sec->hdr.size;
|
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);
|
while (i < chunks.size()) {
|
||||||
cmd.filesize =
|
Chunk &sec = *chunks[i++];
|
||||||
(this == ctx.segments.back()) ? offset : align_to(offset, PAGE_SIZE);
|
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) {
|
void OutputSegment::copy_buf(Context &ctx) {
|
||||||
|
23
test/macho/bss.sh
Executable file
23
test/macho/bss.sh
Executable 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
|
Loading…
Reference in New Issue
Block a user