mirror of
https://github.com/rui314/mold.git
synced 2024-10-26 13:10:46 +03:00
Compare commits
6 Commits
79a72011b7
...
2015347b0c
Author | SHA1 | Date | |
---|---|---|---|
|
2015347b0c | ||
|
4daa9aad36 | ||
|
084ca55a36 | ||
|
e06d886252 | ||
|
9fe3d750cc | ||
|
13bb00bfa2 |
@ -1,6 +1,6 @@
|
||||
.\" generated with Ronn-NG/v0.9.1
|
||||
.\" http://github.com/apjanke/ronn-ng/tree/0.9.1
|
||||
.TH "MOLD" "1" "March 2023" ""
|
||||
.TH "MOLD" "1" "July 2023" ""
|
||||
.SH "NAME"
|
||||
\fBmold\fR \- a modern linker
|
||||
.SH "SYNOPSIS"
|
||||
@ -425,6 +425,9 @@ Some sections such as \fB\.dynamic\fR have to be writable only during an executa
|
||||
.IP
|
||||
By default, \fBmold\fR generates a relro segment\. \fB\-z norelro\fR disables the feature\.
|
||||
.TP
|
||||
\fB\-z sectionheader\fR, \fB\-z nosectionheader\fR
|
||||
\fB\-z nosectionheader\fR tell the linker to omit the section header\. By default, the linker does not omit the section header\.
|
||||
.TP
|
||||
\fB\-z separate\-loadable\-segments\fR, \fB\-z separate\-code\fR, \fB\-z noseparate\-code\fR
|
||||
If one memory page contains multiple segments, the page protection bits are set in such a way that the needed attributes (writable or executable) are satisfied for all segments\. This usually happens at a boundary of two segments with two different attributes\.
|
||||
.IP
|
||||
|
@ -697,6 +697,10 @@ arguments.
|
||||
By default, `mold` generates a relro segment. `-z norelro` disables the
|
||||
feature.
|
||||
|
||||
* `-z sectionheader`, `-z nosectionheader`:
|
||||
`-z nosectionheader` tell the linker to omit the section header.
|
||||
By default, the linker does not omit the section header.
|
||||
|
||||
* `-z separate-loadable-segments`, `-z separate-code`, `-z noseparate-code`:
|
||||
If one memory page contains multiple segments, the page protection bits are
|
||||
set in such a way that the needed attributes (writable or executable) are
|
||||
|
@ -297,7 +297,6 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
|
||||
};
|
||||
|
||||
auto find_paired_reloc = [&] {
|
||||
Symbol<E> &sym = *file.symbols[rels[i].r_sym];
|
||||
assert(sym.get_input_section() == this);
|
||||
|
||||
if (sym.value < r_offset) {
|
||||
|
@ -188,6 +188,8 @@ Options:
|
||||
-z origin Mark object requiring immediate $ORIGIN processing at runtime
|
||||
-z pack-relative-relocs Alias for --pack-dyn-relocs=relr
|
||||
-z nopack-relative-relocs
|
||||
-z sectionheader Do not omit section header (default)
|
||||
-z nosectionheader Omit section header
|
||||
-z separate-loadable-segments
|
||||
Separate all loadable segments to different pages
|
||||
-z separate-code Separate code and data into different pages
|
||||
@ -886,6 +888,10 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
||||
ctx.arg.z_dynamic_undefined_weak = true;
|
||||
} else if (read_z_flag("nodynamic-undefined-weak")) {
|
||||
ctx.arg.z_dynamic_undefined_weak = false;
|
||||
} else if (read_z_flag("sectionheader")) {
|
||||
ctx.arg.z_sectionheader = true;
|
||||
} else if (read_z_flag("nosectionheader")) {
|
||||
ctx.arg.z_sectionheader = false;
|
||||
} else if (read_flag("no-undefined")) {
|
||||
ctx.arg.z_defs = true;
|
||||
} else if (read_flag("fatal-warnings")) {
|
||||
|
@ -273,11 +273,19 @@ void ObjectFile<E>::initialize_sections(Context<E> &ctx) {
|
||||
comdat_groups.push_back({group, (u32)i, entries.subspan(1)});
|
||||
break;
|
||||
}
|
||||
case SHT_REL:
|
||||
if constexpr (E::is_rela)
|
||||
Fatal(ctx) << *this << ": REL-type relocation table is not supported"
|
||||
<< " for this target";
|
||||
break;
|
||||
case SHT_RELA:
|
||||
if constexpr (!E::is_rela)
|
||||
Fatal(ctx) << *this <<": RELA-type relocation table is not supported"
|
||||
<< " for this target";
|
||||
break;
|
||||
case SHT_SYMTAB:
|
||||
case SHT_SYMTAB_SHNDX:
|
||||
case SHT_STRTAB:
|
||||
case SHT_REL:
|
||||
case SHT_RELA:
|
||||
case SHT_NULL:
|
||||
break;
|
||||
default: {
|
||||
@ -1094,6 +1102,11 @@ void ObjectFile<E>::scan_relocations(Context<E> &ctx) {
|
||||
for (ElfRel<E> &rel : cie.get_rels()) {
|
||||
Symbol<E> &sym = *this->symbols[rel.r_sym];
|
||||
|
||||
if (ctx.arg.pic && rel.r_type == E::R_ABS)
|
||||
Error(ctx) << *this << ": relocation " << rel << " in .eh_frame can not"
|
||||
<< " be used when making a position-independent output;"
|
||||
<< " recompile with -fPIE or -fPIC";
|
||||
|
||||
if (sym.is_imported) {
|
||||
if (sym.get_type() != STT_FUNC)
|
||||
Fatal(ctx) << *this << ": " << sym
|
||||
|
@ -1794,6 +1794,7 @@ struct Context {
|
||||
bool z_now = false;
|
||||
bool z_origin = false;
|
||||
bool z_relro = true;
|
||||
bool z_sectionheader = true;
|
||||
bool z_shstk = false;
|
||||
bool z_text = false;
|
||||
i64 filler = -1;
|
||||
|
@ -101,10 +101,12 @@ void OutputEhdr<E>::copy_buf(Context<E> &ctx) {
|
||||
|
||||
// If e_shstrndx is too large, a dummy value is set to e_shstrndx.
|
||||
// The real value is stored to the zero'th section's sh_link field.
|
||||
if (ctx.shstrtab->shndx < SHN_LORESERVE)
|
||||
hdr.e_shstrndx = ctx.shstrtab->shndx;
|
||||
else
|
||||
hdr.e_shstrndx = SHN_XINDEX;
|
||||
if (ctx.shstrtab) {
|
||||
if (ctx.shstrtab->shndx < SHN_LORESERVE)
|
||||
hdr.e_shstrndx = ctx.shstrtab->shndx;
|
||||
else
|
||||
hdr.e_shstrndx = SHN_XINDEX;
|
||||
}
|
||||
|
||||
if (ctx.arg.relocatable)
|
||||
hdr.e_type = ET_REL;
|
||||
@ -140,7 +142,7 @@ void OutputShdr<E>::copy_buf(Context<E> &ctx) {
|
||||
if (UINT16_MAX < shnum)
|
||||
hdr->sh_size = shnum;
|
||||
|
||||
if (SHN_LORESERVE <= ctx.shstrtab->shndx)
|
||||
if (ctx.shstrtab && SHN_LORESERVE <= ctx.shstrtab->shndx)
|
||||
hdr->sh_link = ctx.shstrtab->shndx;
|
||||
|
||||
for (Chunk<E> *chunk : ctx.chunks)
|
||||
@ -1640,7 +1642,10 @@ ElfSym<E> to_output_esym(Context<E> &ctx, Symbol<E> &sym, u32 st_name,
|
||||
// the symbol table.
|
||||
if (shn_xindex) {
|
||||
*shn_xindex = shndx;
|
||||
esym.st_shndx = SHN_XINDEX;
|
||||
if (shndx == SHN_UNDEF || shndx == SHN_ABS || shndx == SHN_COMMON)
|
||||
esym.st_shndx = shndx;
|
||||
else
|
||||
esym.st_shndx = SHN_XINDEX;
|
||||
} else {
|
||||
if (shndx >= SHN_LORESERVE && shndx != SHN_ABS && shndx != SHN_COMMON)
|
||||
Fatal(ctx) << sym << ": internal error: output symbol index too large: "
|
||||
|
@ -57,7 +57,8 @@ void create_synthetic_sections(Context<E> &ctx) {
|
||||
else
|
||||
ctx.phdr = push(new OutputPhdr<E>(0));
|
||||
|
||||
ctx.shdr = push(new OutputShdr<E>);
|
||||
if (ctx.arg.z_sectionheader)
|
||||
ctx.shdr = push(new OutputShdr<E>);
|
||||
}
|
||||
|
||||
ctx.got = push(new GotSection<E>);
|
||||
@ -81,7 +82,7 @@ void create_synthetic_sections(Context<E> &ctx) {
|
||||
ctx.copyrel = push(new CopyrelSection<E>(false));
|
||||
ctx.copyrel_relro = push(new CopyrelSection<E>(true));
|
||||
|
||||
if (!ctx.arg.oformat_binary)
|
||||
if (ctx.shdr)
|
||||
ctx.shstrtab = push(new ShstrtabSection<E>);
|
||||
|
||||
if (!ctx.arg.dynamic_linker.empty())
|
||||
@ -2522,7 +2523,8 @@ i64 compress_debug_sections(Context<E> &ctx) {
|
||||
ctx.chunks[i] = comp;
|
||||
});
|
||||
|
||||
ctx.shstrtab->update_shdr(ctx);
|
||||
if (ctx.shstrtab)
|
||||
ctx.shstrtab->update_shdr(ctx);
|
||||
|
||||
if (ctx.ehdr)
|
||||
ctx.ehdr->update_shdr(ctx);
|
||||
|
@ -54,7 +54,7 @@ fi
|
||||
if [ $MACHINE = x86_64 -o $MACHINE = aarch64 ]; then
|
||||
$CXX -c -o $t/e.o $t/a.cc -mcmodel=large -fno-PIC
|
||||
|
||||
$CXX -B. -o $t/exe9 $t/e.o $static
|
||||
$CXX -B. -o $t/exe9 $t/e.o -no-pie $static
|
||||
$QEMU $t/exe9
|
||||
|
||||
$CXX -B. -o $t/exe10 $t/e.o -no-pie
|
||||
|
15
test/elf/z-sectionheader.sh
Executable file
15
test/elf/z-sectionheader.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
. $(dirname $0)/common.inc
|
||||
|
||||
cat <<EOF | $CC -o $t/a.o -c -xc -
|
||||
#include <stdio.h>
|
||||
int main() {
|
||||
printf("Hello ");
|
||||
puts("world");
|
||||
}
|
||||
EOF
|
||||
|
||||
$CC -B. -o $t/exe $t/a.o -Wl,-z,nosectionheader
|
||||
$QEMU $t/exe | grep -q 'Hello world'
|
||||
|
||||
readelf -h $t/exe 2>&1 | grep -Eq 'Size of section headers:\s+0 '
|
Loading…
Reference in New Issue
Block a user