mirror of
https://github.com/rui314/mold.git
synced 2024-09-20 09:27:45 +03:00
[Mach-O] Add -add_empty_section
This commit is contained in:
parent
883320d5e7
commit
b0c6aa9a0f
@ -20,6 +20,8 @@ Options:
|
||||
-U <SYMBOL> Allow a symbol to be undefined
|
||||
-Z Do not search the standard directories when
|
||||
searching for libraries and frameworks
|
||||
-add_empty_section <SEGNAME> <SECTNAME>
|
||||
Add an empty section
|
||||
-adhoc_codesign Add ad-hoc code signature to the output file
|
||||
-no_adhoc_codesign
|
||||
-all_load Include all objects from static archives
|
||||
@ -194,6 +196,18 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
||||
return false;
|
||||
};
|
||||
|
||||
auto read_arg2 = [&](std::string name) {
|
||||
if (args[i] == name) {
|
||||
if (args.size() <= i + 2)
|
||||
Fatal(ctx) << "option -" << name << ": argument missing";
|
||||
arg = args[i + 1];
|
||||
arg2 = args[i + 2];
|
||||
i += 3;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
auto read_arg3 = [&](std::string name) {
|
||||
if (args[i] == name) {
|
||||
if (args.size() <= i + 3)
|
||||
@ -261,6 +275,8 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
||||
ctx.arg.ObjC = true;
|
||||
} else if (read_arg("-U")) {
|
||||
ctx.arg.U.push_back(std::string(arg));
|
||||
} else if (read_arg2("-add_empty_section")) {
|
||||
ctx.arg.add_empty_section.push_back({arg, arg2});
|
||||
} else if (read_flag("-adhoc_codesign")) {
|
||||
ctx.arg.adhoc_codesign = true;
|
||||
} else if (read_flag("-no_adhoc_codesign")) {
|
||||
|
@ -392,7 +392,14 @@ template <typename E>
|
||||
static void create_synthetic_chunks(Context<E> &ctx) {
|
||||
Timer t(ctx, "create_synthetic_chunks");
|
||||
|
||||
// First, we add subsections specified by -order_file to output sections.
|
||||
// Handle -sectcreate
|
||||
for (SectCreateOption arg : ctx.arg.sectcreate) {
|
||||
MappedFile<Context<E>> *mf =
|
||||
MappedFile<Context<E>>::must_open(ctx, std::string(arg.filename));
|
||||
new SectCreateSection<E>(ctx, arg.segname, arg.sectname, mf->get_contents());
|
||||
}
|
||||
|
||||
// We add subsections specified by -order_file to output sections.
|
||||
for (std::string_view name : ctx.arg.order_file)
|
||||
if (Symbol<E> *sym = get_symbol(ctx, name); sym->file)
|
||||
if (Subsection<E> *subsec = sym->subsec)
|
||||
@ -416,6 +423,15 @@ static void create_synthetic_chunks(Context<E> &ctx) {
|
||||
seg->chunks.push_back(chunk);
|
||||
}
|
||||
|
||||
// Handle -add_empty_section
|
||||
for (AddEmptySectionOption &opt : ctx.arg.add_empty_section) {
|
||||
if (!section_exists(ctx, opt.segname, opt.sectname)) {
|
||||
OutputSegment<E> *seg = OutputSegment<E>::get_instance(ctx, opt.segname);
|
||||
Chunk<E> *sec = new SectCreateSection<E>(ctx, opt.segname, opt.sectname, {});
|
||||
seg->chunks.push_back(sec);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort segments and output sections.
|
||||
sort(ctx.segments, compare_segments<E>);
|
||||
|
||||
@ -423,6 +439,15 @@ static void create_synthetic_chunks(Context<E> &ctx) {
|
||||
sort(seg->chunks, compare_chunks<E>);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
static bool section_exists(Context<E> &ctx, std::string_view segname,
|
||||
std::string_view sectname) {
|
||||
for (Chunk<E> *chunk : ctx.chunks)
|
||||
if (chunk->hdr.match(segname, sectname))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
static void scan_unwind_info(Context<E> &ctx) {
|
||||
tbb::parallel_for_each(ctx.objs, [&](ObjectFile<E> *file) {
|
||||
@ -822,15 +847,6 @@ static int do_main(int argc, char **argv) {
|
||||
tbb::global_control tbb_cont(tbb::global_control::max_allowed_parallelism,
|
||||
ctx.arg.thread_count);
|
||||
|
||||
// Handle -sectcreate
|
||||
for (SectCreateOption arg : ctx.arg.sectcreate) {
|
||||
MappedFile<Context<E>> *mf =
|
||||
MappedFile<Context<E>>::must_open(ctx, std::string(arg.filename));
|
||||
SectCreateSection<E> *sec =
|
||||
new SectCreateSection<E>(ctx, arg.segname, arg.sectname, mf->get_contents());
|
||||
ctx.chunk_pool.emplace_back(sec);
|
||||
}
|
||||
|
||||
if (ctx.arg.adhoc_codesign)
|
||||
ctx.code_sig.reset(new CodeSignatureSection<E>(ctx));
|
||||
|
||||
|
11
macho/mold.h
11
macho/mold.h
@ -707,10 +707,7 @@ template <typename E>
|
||||
class SectCreateSection : public Chunk<E> {
|
||||
public:
|
||||
SectCreateSection(Context<E> &ctx, std::string_view seg, std::string_view sect,
|
||||
std::string_view contents)
|
||||
: Chunk<E>(ctx, seg, sect), contents(contents) {
|
||||
this->hdr.size = contents.size();
|
||||
}
|
||||
std::string_view contents);
|
||||
|
||||
void copy_buf(Context<E> &ctx) override;
|
||||
|
||||
@ -795,6 +792,11 @@ void create_range_extension_thunks(Context<ARM64> &ctx, OutputSection<ARM64> &os
|
||||
|
||||
enum UuidKind { UUID_NONE, UUID_HASH, UUID_RANDOM };
|
||||
|
||||
struct AddEmptySectionOption {
|
||||
std::string_view segname;
|
||||
std::string_view sectname;
|
||||
};
|
||||
|
||||
struct SectCreateOption {
|
||||
std::string_view segname;
|
||||
std::string_view sectname;
|
||||
@ -870,6 +872,7 @@ struct Context {
|
||||
std::string map;
|
||||
std::string object_path_lto;
|
||||
std::string output = "a.out";
|
||||
std::vector<AddEmptySectionOption> add_empty_section;
|
||||
std::vector<SectCreateOption> sectcreate;
|
||||
std::vector<std::string> U;
|
||||
std::vector<std::string> framework_paths;
|
||||
|
@ -1530,6 +1530,15 @@ void ThreadPtrsSection<E>::copy_buf(Context<E> &ctx) {
|
||||
buf[i] = sym.get_addr(ctx);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
SectCreateSection<E>::SectCreateSection(Context<E> &ctx, std::string_view seg,
|
||||
std::string_view sect,
|
||||
std::string_view contents)
|
||||
: Chunk<E>(ctx, seg, sect), contents(contents) {
|
||||
this->hdr.size = contents.size();
|
||||
ctx.chunk_pool.emplace_back(this);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
void SectCreateSection<E>::copy_buf(Context<E> &ctx) {
|
||||
write_string(ctx.buf + this->hdr.offset, contents);
|
||||
|
25
test/macho/add-empty-section.sh
Executable file
25
test/macho/add-empty-section.sh
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
export LC_ALL=C
|
||||
set -e
|
||||
CC="${TEST_CC:-cc}"
|
||||
CXX="${TEST_CXX:-c++}"
|
||||
GCC="${TEST_GCC:-gcc}"
|
||||
GXX="${TEST_GXX:-g++}"
|
||||
OBJDUMP="${OBJDUMP:-objdump}"
|
||||
MACHINE="${MACHINE:-$(uname -m)}"
|
||||
testname=$(basename "$0" .sh)
|
||||
echo -n "Testing $testname ... "
|
||||
cd "$(dirname "$0")"/../..
|
||||
t=out/test/macho/$testname
|
||||
mkdir -p $t
|
||||
|
||||
cat <<EOF | $CC -o $t/a.o -c -xc -
|
||||
int main() {}
|
||||
EOF
|
||||
|
||||
clang --ld-path=./ld64 -o $t/exe $t/a.o -Wl,-add_empty_section,__FOO,__foo
|
||||
|
||||
otool -l $t/exe | grep -q 'segname __FOO'
|
||||
otool -l $t/exe | grep -q 'sectname __foo'
|
||||
|
||||
echo OK
|
Loading…
Reference in New Issue
Block a user