mirror of
https://github.com/rui314/mold.git
synced 2024-09-11 13:06:59 +03:00
Compare commits
2 Commits
3f593c62ae
...
23bc92c66f
Author | SHA1 | Date | |
---|---|---|---|
|
23bc92c66f | ||
|
c2956484ca |
@ -362,7 +362,6 @@ target_sources(mold PRIVATE
|
||||
lib/compress.cc
|
||||
lib/crc32.cc
|
||||
lib/demangle.cc
|
||||
lib/elf.cc
|
||||
lib/filepath.cc
|
||||
lib/glob.cc
|
||||
lib/hyperloglog.cc
|
||||
@ -384,6 +383,7 @@ target_sources(mold PRIVATE
|
||||
src/arch-sparc64.cc
|
||||
src/arch-x86-64.cc
|
||||
src/config.cc
|
||||
src/elf.cc
|
||||
third-party/rust-demangle/rust-demangle.c
|
||||
)
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "filetype.h"
|
||||
|
||||
namespace mold {
|
||||
|
||||
@ -164,14 +163,11 @@ std::vector<MappedFile *> read_fat_archive_members(Context &ctx, MappedFile *mf)
|
||||
|
||||
template <typename Context, typename MappedFile>
|
||||
std::vector<MappedFile *> read_archive_members(Context &ctx, MappedFile *mf) {
|
||||
switch (get_file_type(ctx, mf)) {
|
||||
case FileType::AR:
|
||||
std::string_view str = mf->get_contents();
|
||||
if (str.starts_with("!<arch>\n"))
|
||||
return read_fat_archive_members(ctx, mf);
|
||||
case FileType::THIN_AR:
|
||||
return read_thin_archive_members(ctx, mf);
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
assert(str.starts_with("!<thin>\n"));
|
||||
return read_thin_archive_members(ctx, mf);
|
||||
}
|
||||
|
||||
} // namespace mold
|
||||
|
@ -8,12 +8,12 @@
|
||||
// big-endian SPARC machine to create a little-endian RV64 binary.
|
||||
//
|
||||
// 2. Even though data members in all ELF data strucutres are naturally
|
||||
// aligned, they are not guaranteed to be aligned on memory. Because
|
||||
// archive file (.a file) aligns each member only to a 2 byte boundary,
|
||||
// anything larger than 2 bytes may be unaligned in an mmap'ed memory.
|
||||
// Unaligned access is an undefined behavior in C/C++, so we shouldn't
|
||||
// cast an arbitrary pointer to a uint32_t, for example, to read a
|
||||
// 32 bit value.
|
||||
// aligned, they are not guaranteed to be aligned on memory because of
|
||||
// archive files. Archive files (.a files) align each member only to a
|
||||
// 2 byte boundary, so anything larger than 2 bytes may be misaligned
|
||||
// in an mmap'ed memory. Misaligned access is an undefined behavior in
|
||||
// C/C++, so we shouldn't cast an arbitrary pointer to a uint32_t, for
|
||||
// example, to read a 32 bit value.
|
||||
//
|
||||
// The data types defined in this file don't depend on host byte order and
|
||||
// don't do unaligned access.
|
||||
|
@ -1,3 +1,5 @@
|
||||
// This file contains functions to create a tar file.
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -722,7 +722,11 @@ u64 get_eflags(Context<E> &ctx) {
|
||||
void fixup_arm_exidx_section(Context<E> &ctx) {
|
||||
Timer t(ctx, "fixup_arm_exidx_section");
|
||||
|
||||
OutputSection<E> *osec = find_section(ctx, SHT_ARM_EXIDX);
|
||||
Chunk<E> *chunk = find_chunk(ctx, SHT_ARM_EXIDX);
|
||||
if (!chunk)
|
||||
return;
|
||||
|
||||
OutputSection<E> *osec = chunk->to_osec();
|
||||
if (!osec)
|
||||
return;
|
||||
|
||||
@ -780,7 +784,7 @@ void fixup_arm_exidx_section(Context<E> &ctx) {
|
||||
// .ARM.exidx's sh_link should be set to the .text section index.
|
||||
// Runtime doesn't care about it, but the binutils's strip command does.
|
||||
if (ctx.shdr) {
|
||||
if (Chunk<E> *text = find_section(ctx, ".text")) {
|
||||
if (Chunk<E> *text = find_chunk(ctx, ".text")) {
|
||||
osec->shdr.sh_link = text->shndx;
|
||||
ctx.shdr->copy_buf(ctx);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "integers.h"
|
||||
#include "../lib/integers.h"
|
||||
|
||||
#include <concepts>
|
||||
#include <ostream>
|
||||
@ -191,6 +191,7 @@ enum : u32 {
|
||||
PT_GNU_EH_FRAME = 0x6474e550,
|
||||
PT_GNU_STACK = 0x6474e551,
|
||||
PT_GNU_RELRO = 0x6474e552,
|
||||
PT_GNU_PROPERTY = 0x6474e553,
|
||||
PT_OPENBSD_RANDOMIZE = 0x65a3dbe6,
|
||||
PT_ARM_EXIDX = 0x70000001,
|
||||
PT_RISCV_ATTRIBUTES = 0x70000003,
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include "../lib/common.h"
|
||||
#include "elf.h"
|
||||
|
||||
namespace mold {
|
||||
@ -140,23 +140,23 @@ FileType get_file_type(Context &ctx, MappedFile *mf) {
|
||||
return FileType::UNKNOWN;
|
||||
}
|
||||
|
||||
inline std::string filetype_to_string(FileType type) {
|
||||
switch (type) {
|
||||
case FileType::UNKNOWN: return "UNKNOWN";
|
||||
case FileType::EMPTY: return "EMPTY";
|
||||
case FileType::ELF_OBJ: return "ELF_OBJ";
|
||||
case FileType::ELF_DSO: return "ELF_DSO";
|
||||
case FileType::AR: return "AR";
|
||||
case FileType::THIN_AR: return "THIN_AR";
|
||||
case FileType::TEXT: return "TEXT";
|
||||
case FileType::GCC_LTO_OBJ: return "GCC_LTO_OBJ";
|
||||
case FileType::LLVM_BITCODE: return "LLVM_BITCODE";
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &out, FileType type) {
|
||||
out << filetype_to_string(type);
|
||||
auto to_string = [&] {
|
||||
switch (type) {
|
||||
case FileType::UNKNOWN: return "UNKNOWN";
|
||||
case FileType::EMPTY: return "EMPTY";
|
||||
case FileType::ELF_OBJ: return "ELF_OBJ";
|
||||
case FileType::ELF_DSO: return "ELF_DSO";
|
||||
case FileType::AR: return "AR";
|
||||
case FileType::THIN_AR: return "THIN_AR";
|
||||
case FileType::TEXT: return "TEXT";
|
||||
case FileType::GCC_LTO_OBJ: return "GCC_LTO_OBJ";
|
||||
case FileType::LLVM_BITCODE: return "LLVM_BITCODE";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
};
|
||||
|
||||
out << to_string();
|
||||
return out;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "mold.h"
|
||||
#include "filetype.h"
|
||||
#include "../lib/archive-file.h"
|
||||
#include "../lib/output-file.h"
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "../lib/common.h"
|
||||
#include "../lib/elf.h"
|
||||
#include "elf.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <bitset>
|
||||
@ -341,10 +341,10 @@ template <typename E> u64 get_dtp_addr(const ElfPhdr<E> &);
|
||||
//
|
||||
|
||||
template <typename E>
|
||||
OutputSection<E> *find_section(Context<E> &ctx, u32 sh_type);
|
||||
Chunk<E> *find_chunk(Context<E> &ctx, u32 sh_type);
|
||||
|
||||
template <typename E>
|
||||
OutputSection<E> *find_section(Context<E> &ctx, std::string_view name);
|
||||
Chunk<E> *find_chunk(Context<E> &ctx, std::string_view name);
|
||||
|
||||
template <typename E>
|
||||
u64 get_eflags(Context<E> &ctx) {
|
||||
|
@ -25,20 +25,18 @@ static u32 elf_hash(std::string_view name) {
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
OutputSection<E> *find_section(Context<E> &ctx, u32 sh_type) {
|
||||
Chunk<E> *find_chunk(Context<E> &ctx, u32 sh_type) {
|
||||
for (Chunk<E> *chunk : ctx.chunks)
|
||||
if (OutputSection<E> *osec = chunk->to_osec())
|
||||
if (osec->shdr.sh_type == sh_type)
|
||||
return osec;
|
||||
if (chunk->shdr.sh_type == sh_type)
|
||||
return chunk;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
OutputSection<E> *find_section(Context<E> &ctx, std::string_view name) {
|
||||
Chunk<E> *find_chunk(Context<E> &ctx, std::string_view name) {
|
||||
for (Chunk<E> *chunk : ctx.chunks)
|
||||
if (OutputSection<E> *osec = chunk->to_osec())
|
||||
if (osec->name == name)
|
||||
return osec;
|
||||
if (chunk->name == name)
|
||||
return chunk;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -267,6 +265,10 @@ static std::vector<ElfPhdr<E>> create_phdr(Context<E> &ctx) {
|
||||
if (ctx.eh_frame_hdr)
|
||||
define(PT_GNU_EH_FRAME, PF_R, ctx.eh_frame_hdr);
|
||||
|
||||
// Add PT_GNU_PROPERTY
|
||||
if (Chunk<E> *chunk = find_chunk(ctx, ".note.gnu.property"))
|
||||
define(PT_GNU_PROPERTY, PF_R, chunk);
|
||||
|
||||
// Add PT_GNU_STACK, which is a marker segment that doesn't really
|
||||
// contain any segments. It controls executable bit of stack area.
|
||||
{
|
||||
@ -293,8 +295,8 @@ static std::vector<ElfPhdr<E>> create_phdr(Context<E> &ctx) {
|
||||
|
||||
// Create a PT_ARM_EDXIDX
|
||||
if constexpr (is_arm32<E>)
|
||||
if (OutputSection<E> *osec = find_section(ctx, SHT_ARM_EXIDX))
|
||||
define(PT_ARM_EXIDX, PF_R, osec);
|
||||
if (Chunk<E> *chunk = find_chunk(ctx, SHT_ARM_EXIDX))
|
||||
define(PT_ARM_EXIDX, PF_R, chunk);
|
||||
|
||||
// Create a PT_RISCV_ATTRIBUTES
|
||||
if constexpr (is_riscv<E>)
|
||||
@ -734,19 +736,19 @@ static std::vector<Word<E>> create_dynamic_section(Context<E> &ctx) {
|
||||
define(DT_STRSZ, ctx.dynstr->shdr.sh_size);
|
||||
}
|
||||
|
||||
if (find_section(ctx, SHT_INIT_ARRAY)) {
|
||||
if (find_chunk(ctx, SHT_INIT_ARRAY)) {
|
||||
define(DT_INIT_ARRAY, ctx.__init_array_start->value);
|
||||
define(DT_INIT_ARRAYSZ,
|
||||
ctx.__init_array_end->value - ctx.__init_array_start->value);
|
||||
}
|
||||
|
||||
if (find_section(ctx, SHT_PREINIT_ARRAY)) {
|
||||
if (find_chunk(ctx, SHT_PREINIT_ARRAY)) {
|
||||
define(DT_PREINIT_ARRAY, ctx.__preinit_array_start->value);
|
||||
define(DT_PREINIT_ARRAYSZ,
|
||||
ctx.__preinit_array_end->value - ctx.__preinit_array_start->value);
|
||||
}
|
||||
|
||||
if (find_section(ctx, SHT_FINI_ARRAY)) {
|
||||
if (find_chunk(ctx, SHT_FINI_ARRAY)) {
|
||||
define(DT_FINI_ARRAY, ctx.__fini_array_start->value);
|
||||
define(DT_FINI_ARRAYSZ,
|
||||
ctx.__fini_array_end->value - ctx.__fini_array_start->value);
|
||||
@ -2949,8 +2951,8 @@ template class RelocSection<E>;
|
||||
template class ComdatGroupSection<E>;
|
||||
template class GnuDebuglinkSection<E>;
|
||||
|
||||
template OutputSection<E> *find_section(Context<E> &, u32);
|
||||
template OutputSection<E> *find_section(Context<E> &, std::string_view);
|
||||
template Chunk<E> *find_chunk(Context<E> &, u32);
|
||||
template Chunk<E> *find_chunk(Context<E> &, std::string_view);
|
||||
template i64 to_phdr_flags(Context<E> &ctx, Chunk<E> *chunk);
|
||||
template ElfSym<E> to_output_esym(Context<E> &, Symbol<E> &, u32, U32<E> *);
|
||||
|
||||
|
@ -1271,10 +1271,13 @@ void fixup_ctors_in_init_array(Context<E> &ctx) {
|
||||
}
|
||||
};
|
||||
|
||||
if (OutputSection<E> *osec = find_section(ctx, ".init_array"))
|
||||
fixup(*osec);
|
||||
if (OutputSection<E> *osec = find_section(ctx, ".fini_array"))
|
||||
fixup(*osec);
|
||||
if (Chunk<E> *chunk = find_chunk(ctx, ".init_array"))
|
||||
if (OutputSection<E> *osec = chunk->to_osec())
|
||||
fixup(*osec);
|
||||
|
||||
if (Chunk<E> *chunk = find_chunk(ctx, ".fini_array"))
|
||||
if (OutputSection<E> *osec = chunk->to_osec())
|
||||
fixup(*osec);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
10
test/gnu-property.sh
Normal file
10
test/gnu-property.sh
Normal file
@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
. $(dirname $0)/common.inc
|
||||
|
||||
cat <<EOF | $CC -o $t/a.o -c -xc -
|
||||
int main() {}
|
||||
EOF
|
||||
|
||||
$CC -B. -o $t/exe $t/a.o -no-pie
|
||||
readelf -W --sections $t/exe | grep -Fqw .note.gnu.property || skip
|
||||
readelf -W --segments $t/exe | grep -qw GNU_PROPERTY
|
Loading…
Reference in New Issue
Block a user