]>
git.ipfire.org Git - people/ms/u-boot.git/blob - tools/relocate-rela.c
2 * Copyright 2013 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0+ BSD-2-Clause
6 * 64-bit and little-endian target only until we need to support a different
7 * 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
, ...)
34 static bool supported_rela(Elf64_Rela
*rela
)
36 uint64_t mask
= 0xffffffffULL
; /* would be different on 32-bit */
37 uint32_t type
= rela
->r_info
& mask
;
40 #ifdef R_AARCH64_RELATIVE
41 case R_AARCH64_RELATIVE
:
45 fprintf(stderr
, "warning: unsupported relocation type %"
46 PRIu32
" at %" PRIx64
"\n",
47 type
, rela
->r_offset
);
53 static inline uint64_t swap64(uint64_t val
)
55 return ((val
>> 56) & 0x00000000000000ffULL
) |
56 ((val
>> 40) & 0x000000000000ff00ULL
) |
57 ((val
>> 24) & 0x0000000000ff0000ULL
) |
58 ((val
>> 8) & 0x00000000ff000000ULL
) |
59 ((val
<< 8) & 0x000000ff00000000ULL
) |
60 ((val
<< 24) & 0x0000ff0000000000ULL
) |
61 ((val
<< 40) & 0x00ff000000000000ULL
) |
62 ((val
<< 56) & 0xff00000000000000ULL
);
65 #if __BYTE_ORDER == __LITTLE_ENDIAN
66 static inline uint64_t be64(uint64_t val
)
71 static inline uint64_t le64(uint64_t val
)
76 static inline uint64_t le64(uint64_t val
)
81 static inline uint64_t be64(uint64_t val
)
87 static bool read_num(const char *str
, uint64_t *num
)
90 *num
= strtoull(str
, &endptr
, 16);
91 return str
[0] && !endptr
[0];
94 int main(int argc
, char **argv
)
98 uint64_t rela_start
, rela_end
, text_base
;
101 fprintf(stderr
, "Statically apply ELF rela relocations\n");
102 fprintf(stderr
, "Usage: %s <bin file> <text base> " \
103 "<rela start> <rela end>\n", argv
[0]);
104 fprintf(stderr
, "All numbers in hex.\n");
108 f
= fopen(argv
[1], "r+b");
110 fprintf(stderr
, "%s: Cannot open %s: %s\n",
111 argv
[0], argv
[1], strerror(errno
));
115 if (!read_num(argv
[2], &text_base
) ||
116 !read_num(argv
[3], &rela_start
) ||
117 !read_num(argv
[4], &rela_end
)) {
118 fprintf(stderr
, "%s: bad number\n", argv
[0]);
122 if (rela_start
> rela_end
|| rela_start
< text_base
||
123 (rela_end
- rela_start
) % sizeof(Elf64_Rela
)) {
124 fprintf(stderr
, "%s: bad rela bounds\n", argv
[0]);
128 rela_start
-= text_base
;
129 rela_end
-= text_base
;
131 num
= (rela_end
- rela_start
) / sizeof(Elf64_Rela
);
133 for (i
= 0; i
< num
; i
++) {
134 Elf64_Rela rela
, swrela
;
135 uint64_t pos
= rela_start
+ sizeof(Elf64_Rela
) * i
;
138 if (fseek(f
, pos
, SEEK_SET
) < 0) {
139 fprintf(stderr
, "%s: %s: seek to %" PRIx64
141 argv
[0], argv
[1], pos
, strerror(errno
));
144 if (fread(&rela
, sizeof(rela
), 1, f
) != 1) {
145 fprintf(stderr
, "%s: %s: read rela failed at %"
147 argv
[0], argv
[1], pos
);
151 swrela
.r_offset
= le64(rela
.r_offset
);
152 swrela
.r_info
= le64(rela
.r_info
);
153 swrela
.r_addend
= le64(rela
.r_addend
);
155 if (!supported_rela(&swrela
))
158 debug("Rela %" PRIx64
" %" PRIu64
" %" PRIx64
"\n",
159 swrela
.r_offset
, swrela
.r_info
, swrela
.r_addend
);
161 if (swrela
.r_offset
< text_base
) {
162 fprintf(stderr
, "%s: %s: bad rela at %" PRIx64
"\n",
163 argv
[0], argv
[1], pos
);
167 addr
= swrela
.r_offset
- text_base
;
169 if (fseek(f
, addr
, SEEK_SET
) < 0) {
170 fprintf(stderr
, "%s: %s: seek to %"
171 PRIx64
" failed: %s\n",
172 argv
[0], argv
[1], addr
, strerror(errno
));
175 if (fwrite(&rela
.r_addend
, sizeof(rela
.r_addend
), 1, f
) != 1) {
176 fprintf(stderr
, "%s: %s: write failed at %" PRIx64
"\n",
177 argv
[0], argv
[1], addr
);
183 fprintf(stderr
, "%s: %s: close failed: %s\n",
184 argv
[0], argv
[1], strerror(errno
));