1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-2-Clause
3 * Copyright 2013 Freescale Semiconductor, Inc.
5 * 64-bit and little-endian target only until we need to support a different
6 * arch that needs this.
19 #ifndef R_AARCH64_RELATIVE
20 #define R_AARCH64_RELATIVE 1027
23 static const bool debug_en
;
25 static void debug(const char *fmt
, ...)
36 static bool supported_rela(Elf64_Rela
*rela
)
38 uint64_t mask
= 0xffffffffULL
; /* would be different on 32-bit */
39 uint32_t type
= rela
->r_info
& mask
;
42 #ifdef R_AARCH64_RELATIVE
43 case R_AARCH64_RELATIVE
:
47 fprintf(stderr
, "warning: unsupported relocation type %"
48 PRIu32
" at %" PRIx64
"\n",
49 type
, rela
->r_offset
);
55 static bool read_num(const char *str
, uint64_t *num
)
58 *num
= strtoull(str
, &endptr
, 16);
59 return str
[0] && !endptr
[0];
62 int main(int argc
, char **argv
)
66 uint64_t rela_start
, rela_end
, text_base
;
69 fprintf(stderr
, "Statically apply ELF rela relocations\n");
70 fprintf(stderr
, "Usage: %s <bin file> <text base> " \
71 "<rela start> <rela end>\n", argv
[0]);
72 fprintf(stderr
, "All numbers in hex.\n");
76 f
= fopen(argv
[1], "r+b");
78 fprintf(stderr
, "%s: Cannot open %s: %s\n",
79 argv
[0], argv
[1], strerror(errno
));
83 if (!read_num(argv
[2], &text_base
) ||
84 !read_num(argv
[3], &rela_start
) ||
85 !read_num(argv
[4], &rela_end
)) {
86 fprintf(stderr
, "%s: bad number\n", argv
[0]);
90 if (rela_start
> rela_end
|| rela_start
< text_base
||
91 (rela_end
- rela_start
) % sizeof(Elf64_Rela
)) {
92 fprintf(stderr
, "%s: bad rela bounds\n", argv
[0]);
96 rela_start
-= text_base
;
97 rela_end
-= text_base
;
99 num
= (rela_end
- rela_start
) / sizeof(Elf64_Rela
);
101 for (i
= 0; i
< num
; i
++) {
102 Elf64_Rela rela
, swrela
;
103 uint64_t pos
= rela_start
+ sizeof(Elf64_Rela
) * i
;
106 if (fseek(f
, pos
, SEEK_SET
) < 0) {
107 fprintf(stderr
, "%s: %s: seek to %" PRIx64
109 argv
[0], argv
[1], pos
, strerror(errno
));
112 if (fread(&rela
, sizeof(rela
), 1, f
) != 1) {
113 fprintf(stderr
, "%s: %s: read rela failed at %"
115 argv
[0], argv
[1], pos
);
119 swrela
.r_offset
= cpu_to_le64(rela
.r_offset
);
120 swrela
.r_info
= cpu_to_le64(rela
.r_info
);
121 swrela
.r_addend
= cpu_to_le64(rela
.r_addend
);
123 if (!supported_rela(&swrela
))
126 debug("Rela %" PRIx64
" %" PRIu64
" %" PRIx64
"\n",
127 swrela
.r_offset
, swrela
.r_info
, swrela
.r_addend
);
129 if (swrela
.r_offset
< text_base
) {
130 fprintf(stderr
, "%s: %s: bad rela at %" PRIx64
"\n",
131 argv
[0], argv
[1], pos
);
135 addr
= swrela
.r_offset
- text_base
;
137 if (fseek(f
, addr
, SEEK_SET
) < 0) {
138 fprintf(stderr
, "%s: %s: seek to %"
139 PRIx64
" failed: %s\n",
140 argv
[0], argv
[1], addr
, strerror(errno
));
143 if (fwrite(&rela
.r_addend
, sizeof(rela
.r_addend
), 1, f
) != 1) {
144 fprintf(stderr
, "%s: %s: write failed at %" PRIx64
"\n",
145 argv
[0], argv
[1], addr
);
151 fprintf(stderr
, "%s: %s: close failed: %s\n",
152 argv
[0], argv
[1], strerror(errno
));