mirror of
https://github.com/rui314/mold.git
synced 2024-11-10 10:57:55 +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
|
-U <SYMBOL> Allow a symbol to be undefined
|
||||||
-Z Do not search the standard directories when
|
-Z Do not search the standard directories when
|
||||||
searching for libraries and frameworks
|
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
|
-adhoc_codesign Add ad-hoc code signature to the output file
|
||||||
-no_adhoc_codesign
|
-no_adhoc_codesign
|
||||||
-all_load Include all objects from static archives
|
-all_load Include all objects from static archives
|
||||||
@ -194,6 +196,18 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
|||||||
return false;
|
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) {
|
auto read_arg3 = [&](std::string name) {
|
||||||
if (args[i] == name) {
|
if (args[i] == name) {
|
||||||
if (args.size() <= i + 3)
|
if (args.size() <= i + 3)
|
||||||
@ -261,6 +275,8 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
|||||||
ctx.arg.ObjC = true;
|
ctx.arg.ObjC = true;
|
||||||
} else if (read_arg("-U")) {
|
} else if (read_arg("-U")) {
|
||||||
ctx.arg.U.push_back(std::string(arg));
|
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")) {
|
} else if (read_flag("-adhoc_codesign")) {
|
||||||
ctx.arg.adhoc_codesign = true;
|
ctx.arg.adhoc_codesign = true;
|
||||||
} else if (read_flag("-no_adhoc_codesign")) {
|
} else if (read_flag("-no_adhoc_codesign")) {
|
||||||
|
@ -392,7 +392,14 @@ template <typename E>
|
|||||||
static void create_synthetic_chunks(Context<E> &ctx) {
|
static void create_synthetic_chunks(Context<E> &ctx) {
|
||||||
Timer t(ctx, "create_synthetic_chunks");
|
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)
|
for (std::string_view name : ctx.arg.order_file)
|
||||||
if (Symbol<E> *sym = get_symbol(ctx, name); sym->file)
|
if (Symbol<E> *sym = get_symbol(ctx, name); sym->file)
|
||||||
if (Subsection<E> *subsec = sym->subsec)
|
if (Subsection<E> *subsec = sym->subsec)
|
||||||
@ -416,6 +423,15 @@ static void create_synthetic_chunks(Context<E> &ctx) {
|
|||||||
seg->chunks.push_back(chunk);
|
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 segments and output sections.
|
||||||
sort(ctx.segments, compare_segments<E>);
|
sort(ctx.segments, compare_segments<E>);
|
||||||
|
|
||||||
@ -423,6 +439,15 @@ static void create_synthetic_chunks(Context<E> &ctx) {
|
|||||||
sort(seg->chunks, compare_chunks<E>);
|
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>
|
template <typename E>
|
||||||
static void scan_unwind_info(Context<E> &ctx) {
|
static void scan_unwind_info(Context<E> &ctx) {
|
||||||
tbb::parallel_for_each(ctx.objs, [&](ObjectFile<E> *file) {
|
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,
|
tbb::global_control tbb_cont(tbb::global_control::max_allowed_parallelism,
|
||||||
ctx.arg.thread_count);
|
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)
|
if (ctx.arg.adhoc_codesign)
|
||||||
ctx.code_sig.reset(new CodeSignatureSection<E>(ctx));
|
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> {
|
class SectCreateSection : public Chunk<E> {
|
||||||
public:
|
public:
|
||||||
SectCreateSection(Context<E> &ctx, std::string_view seg, std::string_view sect,
|
SectCreateSection(Context<E> &ctx, std::string_view seg, std::string_view sect,
|
||||||
std::string_view contents)
|
std::string_view contents);
|
||||||
: Chunk<E>(ctx, seg, sect), contents(contents) {
|
|
||||||
this->hdr.size = contents.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_buf(Context<E> &ctx) override;
|
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 };
|
enum UuidKind { UUID_NONE, UUID_HASH, UUID_RANDOM };
|
||||||
|
|
||||||
|
struct AddEmptySectionOption {
|
||||||
|
std::string_view segname;
|
||||||
|
std::string_view sectname;
|
||||||
|
};
|
||||||
|
|
||||||
struct SectCreateOption {
|
struct SectCreateOption {
|
||||||
std::string_view segname;
|
std::string_view segname;
|
||||||
std::string_view sectname;
|
std::string_view sectname;
|
||||||
@ -870,6 +872,7 @@ struct Context {
|
|||||||
std::string map;
|
std::string map;
|
||||||
std::string object_path_lto;
|
std::string object_path_lto;
|
||||||
std::string output = "a.out";
|
std::string output = "a.out";
|
||||||
|
std::vector<AddEmptySectionOption> add_empty_section;
|
||||||
std::vector<SectCreateOption> sectcreate;
|
std::vector<SectCreateOption> sectcreate;
|
||||||
std::vector<std::string> U;
|
std::vector<std::string> U;
|
||||||
std::vector<std::string> framework_paths;
|
std::vector<std::string> framework_paths;
|
||||||
|
@ -1530,6 +1530,15 @@ void ThreadPtrsSection<E>::copy_buf(Context<E> &ctx) {
|
|||||||
buf[i] = sym.get_addr(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>
|
template <typename E>
|
||||||
void SectCreateSection<E>::copy_buf(Context<E> &ctx) {
|
void SectCreateSection<E>::copy_buf(Context<E> &ctx) {
|
||||||
write_string(ctx.buf + this->hdr.offset, contents);
|
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