1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-21 01:47:11 +03:00

[Mach-O] Emit __data_in_code

This commit is contained in:
Rui Ueyama 2021-11-03 21:10:03 +09:00
parent bfa50ac015
commit 0f2dbbc09d
5 changed files with 76 additions and 3 deletions

View File

@ -498,7 +498,7 @@ struct SourceVersionCommand {
struct DataInCodeEntry {
u32 offset;
u32 length;
u16 length;
u16 kind;
};

View File

@ -83,9 +83,11 @@ static bool compare_chunks(const Chunk *a, const Chunk *b) {
// __LINKEDIT
"__rebase",
"__binding",
"__weak_binding",
"__lazy_binding",
"__export",
"__func_starts",
"__data_in_code",
"__symbol_table",
"__ind_sym_tab",
"__string_table",

View File

@ -80,6 +80,7 @@ public:
std::vector<std::unique_ptr<InputSection>> sections;
std::span<MachSym> mach_syms;
std::vector<UnwindRecord> unwind_records;
std::span<DataInCodeEntry> data_in_code_entries;
private:
void override_symbol(Context &ctx, Symbol &sym, MachSym &msym);
@ -468,6 +469,20 @@ public:
static constexpr i64 BLOCK_SIZE = 4096;
};
class DataInCodeSection : public Chunk {
public:
DataInCodeSection(Context &ctx)
: Chunk(ctx, "__LINKEDIT", "__data_in_code") {
is_hidden = true;
hdr.p2align = __builtin_ctz(alignof(DataInCodeEntry));
}
void compute_size(Context &ctx) override;
void copy_buf(Context &ctx) override;
std::vector<DataInCodeEntry> contents;
};
class StubsSection : public Chunk {
public:
StubsSection(Context &ctx) : Chunk(ctx, "__TEXT", "__stubs") {
@ -714,6 +729,7 @@ struct Context {
GotSection got{*this};
LazySymbolPtrSection lazy_symbol_ptr{*this};
CodeSignatureSection code_sig{*this};
DataInCodeSection data_in_code{*this};
OutputRebaseSection rebase{*this};
OutputBindSection bind{*this};

View File

@ -5,7 +5,10 @@
namespace mold::macho {
std::ostream &operator<<(std::ostream &out, const InputFile &file) {
out << path_clean(file.mf->name);
if (file.archive_name.empty())
out << path_clean(file.mf->name);
else
out << path_clean(file.archive_name) << "(" << path_clean(file.mf->name) + ")";
return out;
}
@ -58,8 +61,13 @@ void ObjectFile::parse(Context &ctx) {
case LC_DYSYMTAB:
case LC_BUILD_VERSION:
case LC_VERSION_MIN_MACOSX:
case LC_DATA_IN_CODE:
break;
case LC_DATA_IN_CODE: {
LinkEditDataCommand &cmd = *(LinkEditDataCommand *)p;
data_in_code_entries = {(DataInCodeEntry *)(mf->data + cmd.dataoff),
cmd.datasize / sizeof(DataInCodeEntry)};
break;
}
default:
Error(ctx) << *this << ": unknown load command: 0x" << std::hex << lc.cmd;
}

View File

@ -170,6 +170,17 @@ static std::vector<u8> create_function_starts_cmd(Context &ctx) {
return buf;
}
static std::vector<u8> create_data_in_code_cmd(Context &ctx) {
std::vector<u8> buf(sizeof(LinkEditDataCommand));
LinkEditDataCommand &cmd = *(LinkEditDataCommand *)buf.data();
cmd.cmd = LC_DATA_IN_CODE;
cmd.cmdsize = buf.size();
cmd.dataoff = ctx.data_in_code.hdr.offset;
cmd.datasize = ctx.data_in_code.hdr.size;
return buf;
}
static std::vector<u8> create_code_signature_cmd(Context &ctx) {
std::vector<u8> buf(sizeof(LinkEditDataCommand));
LinkEditDataCommand &cmd = *(LinkEditDataCommand *)buf.data();
@ -224,6 +235,8 @@ static std::pair<i64, std::vector<u8>> create_load_commands(Context &ctx) {
for (DylibFile *dylib : ctx.dylibs)
vec.push_back(create_load_dylib_cmd(ctx, dylib->install_name));
vec.push_back(create_function_starts_cmd(ctx));
if (!ctx.data_in_code.contents.empty())
vec.push_back(create_data_in_code_cmd(ctx));
if (ctx.arg.adhoc_codesign)
vec.push_back(create_code_signature_cmd(ctx));
return {vec.size(), flatten(vec)};
@ -867,6 +880,40 @@ void CodeSignatureSection::write_signature(Context &ctx) {
}
}
void DataInCodeSection::compute_size(Context &ctx) {
assert(contents.empty());
for (ObjectFile *file : ctx.objs) {
std::span<DataInCodeEntry> entries = file->data_in_code_entries;
for (i64 i = 0; !entries.empty() && i < file->sections.size(); i++) {
InputSection &sec = *file->sections[i];
for (i64 j = 0; !entries.empty() && j < sec.subsections.size(); j++) {
Subsection &subsec = *sec.subsections[j];
DataInCodeEntry &ent = entries[0];
if (subsec.input_addr + subsec.input_size < ent.offset)
continue;
if (ent.offset < subsec.input_addr + subsec.input_size) {
u32 offset = subsec.get_addr(ctx) + subsec.input_addr - ent.offset -
ctx.text_seg->cmd.vmaddr;
contents.push_back({offset, ent.length, ent.kind});
}
entries = entries.subspan(1);
}
}
}
hdr.size = contents.size() * sizeof(contents[0]);
}
void DataInCodeSection::copy_buf(Context &ctx) {
write_vector(ctx.buf + hdr.offset, contents);
}
void StubsSection::add(Context &ctx, Symbol *sym) {
assert(sym->stub_idx == -1);
sym->stub_idx = syms.size();