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:
parent
bfa50ac015
commit
0f2dbbc09d
@ -498,7 +498,7 @@ struct SourceVersionCommand {
|
||||
|
||||
struct DataInCodeEntry {
|
||||
u32 offset;
|
||||
u32 length;
|
||||
u16 length;
|
||||
u16 kind;
|
||||
};
|
||||
|
||||
|
@ -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",
|
||||
|
16
macho/mold.h
16
macho/mold.h
@ -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};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user