Skip to content

Commit f082360

Browse files
committed
Support CREL as input section
1 parent 6e3d0e3 commit f082360

File tree

6 files changed

+67
-13
lines changed

6 files changed

+67
-13
lines changed

.github/workflows/ci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ jobs:
7070
- gentoo/stage3
7171
- opensuse/tumbleweed
7272
- ubuntu:22.04
73+
- ubuntu:25.04
7374
runs-on: ubuntu-latest
7475
container: ${{ matrix.distro }}
7576
steps:

install-build-deps.sh

+1-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ set -x
1010
case "$ID" in
1111
ubuntu | pop | linuxmint | debian | raspbian | neon)
1212
apt-get update
13-
apt-get install -y cmake gcc g++
14-
if [ "$ID-$VERSION_ID" = ubuntu-20.04 ]; then apt-get install -y g++-10; fi
13+
apt-get install -y cmake gcc g++ clang gdb
1514
;;
1615
fedora | amzn | rhel | centos)
1716
dnf install -y gcc-g++ cmake glibc-static libstdc++-static diffutils util-linux tar

lib/common.h

+17
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,23 @@ inline u64 read_uleb(u8 *buf) {
490490
return read_uleb(&tmp);
491491
}
492492

493+
inline i64 read_sleb(u8 **buf) {
494+
u64 val = 0;
495+
u8 shift = 0;
496+
u8 byte;
497+
do {
498+
byte = *(*buf)++;
499+
val |= (byte & 0x7f) << shift;
500+
shift += 7;
501+
} while (byte & 0x80);
502+
return sign_extend(val, shift);
503+
}
504+
505+
inline i64 read_sleb(u8 *buf) {
506+
u8 *tmp = buf;
507+
return read_sleb(&tmp);
508+
}
509+
493510
inline u64 read_uleb(std::string_view *str) {
494511
u8 *start = (u8 *)str->data();
495512
u8 *ptr = start;

src/elf.h

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ enum : u32 {
7878
SHT_GROUP = 17,
7979
SHT_SYMTAB_SHNDX = 18,
8080
SHT_RELR = 19,
81+
SHT_CREL = 0x40000014,
8182
SHT_LOOS = 0x60000000,
8283
SHT_LLVM_ADDRSIG = 0x6fff4c03,
8384
SHT_GNU_HASH = 0x6ffffff6,

src/input-files.cc

+41-10
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,37 @@ static bool is_known_section_type(const ElfShdr<E> &shdr) {
236236
return false;
237237
}
238238

239+
template <typename E>
240+
std::vector<ElfRel<E>> decode_crel(Context<E> &ctx, std::string_view contents) {
241+
u8 *p = (u8 *)contents.data();
242+
u64 hdr = read_uleb(&p);
243+
i64 nrels = hdr >> 3;
244+
i64 nflags = (hdr & 0b100) ? 3 : 2;
245+
i64 scale = hdr & 0b11;
246+
247+
i64 offset = 0;
248+
i64 addend = 0;
249+
i64 symidx = 0;
250+
i64 type = 0;
251+
252+
std::vector<ElfRel<E>> vec;
253+
vec.reserve(nrels);
254+
255+
while (vec.size() < nrels) {
256+
u64 val = read_uleb(&p);
257+
offset += (val >> nflags) << scale;
258+
259+
if (val & 1)
260+
symidx += read_sleb(&p);
261+
if (val & 2)
262+
type += read_sleb(&p);
263+
if (nflags == 3 && (val & 4))
264+
addend += read_sleb(&p);
265+
vec.emplace_back(offset, type, symidx, addend);
266+
}
267+
return vec;
268+
}
269+
239270
template <typename E>
240271
void ObjectFile<E>::initialize_sections(Context<E> &ctx) {
241272
// Read sections
@@ -300,6 +331,10 @@ void ObjectFile<E>::initialize_sections(Context<E> &ctx) {
300331
comdat_groups.push_back({group, (i32)i, entries.subspan(1)});
301332
break;
302333
}
334+
case SHT_CREL:
335+
decoded_crel.resize(i + 1);
336+
decoded_crel[i] = decode_crel(ctx, this->get_string(ctx, shdr));
337+
break;
303338
case SHT_REL:
304339
case SHT_RELA:
305340
case SHT_SYMTAB:
@@ -436,16 +471,12 @@ void ObjectFile<E>::initialize_sections(Context<E> &ctx) {
436471
// Attach relocation sections to their target sections.
437472
for (i64 i = 0; i < this->elf_sections.size(); i++) {
438473
const ElfShdr<E> &shdr = this->elf_sections[i];
439-
if (shdr.sh_type != (E::is_rela ? SHT_RELA : SHT_REL))
440-
continue;
441-
442-
if (shdr.sh_info >= sections.size())
443-
Fatal(ctx) << *this << ": invalid relocated section index: "
444-
<< (u32)shdr.sh_info;
445-
446-
if (std::unique_ptr<InputSection<E>> &target = sections[shdr.sh_info]) {
447-
assert(target->relsec_idx == -1);
448-
target->relsec_idx = i;
474+
if (shdr.sh_type == (E::is_rela ? SHT_RELA : SHT_REL) ||
475+
shdr.sh_type == SHT_CREL) {
476+
if (std::unique_ptr<InputSection<E>> &target = sections[shdr.sh_info]) {
477+
assert(target->relsec_idx == -1);
478+
target->relsec_idx = i;
479+
}
449480
}
450481
}
451482

src/mold.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,7 @@ class ObjectFile : public InputFile<E> {
14181418
std::vector<bool> has_symver;
14191419
std::vector<ComdatGroupRef<E>> comdat_groups;
14201420
std::vector<InputSection<E> *> eh_frame_sections;
1421+
std::vector<std::vector<ElfRel<E>>> decoded_crel;
14211422
bool exclude_libs = false;
14221423
std::map<u32, u32> gnu_properties;
14231424
bool needs_executable_stack = false;
@@ -2573,7 +2574,11 @@ template <typename E>
25732574
inline std::span<ElfRel<E>> InputSection<E>::get_rels(Context<E> &ctx) const {
25742575
if (relsec_idx == -1)
25752576
return {};
2576-
return file.template get_data<ElfRel<E>>(ctx, file.elf_sections[relsec_idx]);
2577+
2578+
ElfShdr<E> &shdr = file.elf_sections[relsec_idx];
2579+
if (shdr.sh_type == SHT_CREL)
2580+
return file.decoded_crel[relsec_idx];
2581+
return file.template get_data<ElfRel<E>>(ctx, shdr);
25772582
}
25782583

25792584
template <typename E>

0 commit comments

Comments
 (0)