aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/recordmcount.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/recordmcount.c')
-rw-r--r--scripts/recordmcount.c137
1 files changed, 113 insertions, 24 deletions
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 698768bdc581..301d70b0174f 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -48,12 +48,17 @@
48 48
49static int fd_map; /* File descriptor for file being modified. */ 49static int fd_map; /* File descriptor for file being modified. */
50static int mmap_failed; /* Boolean flag. */ 50static int mmap_failed; /* Boolean flag. */
51static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
52static char gpfx; /* prefix for global symbol name (sometimes '_') */ 51static char gpfx; /* prefix for global symbol name (sometimes '_') */
53static struct stat sb; /* Remember .st_size, etc. */ 52static struct stat sb; /* Remember .st_size, etc. */
54static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */ 53static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
55static const char *altmcount; /* alternate mcount symbol name */ 54static const char *altmcount; /* alternate mcount symbol name */
56static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */ 55static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
56static void *file_map; /* pointer of the mapped file */
57static void *file_end; /* pointer to the end of the mapped file */
58static int file_updated; /* flag to state file was changed */
59static void *file_ptr; /* current file pointer location */
60static void *file_append; /* added to the end of the file */
61static size_t file_append_size; /* how much is added to end of file */
57 62
58/* setjmp() return values */ 63/* setjmp() return values */
59enum { 64enum {
@@ -67,10 +72,14 @@ static void
67cleanup(void) 72cleanup(void)
68{ 73{
69 if (!mmap_failed) 74 if (!mmap_failed)
70 munmap(ehdr_curr, sb.st_size); 75 munmap(file_map, sb.st_size);
71 else 76 else
72 free(ehdr_curr); 77 free(file_map);
73 close(fd_map); 78 file_map = NULL;
79 free(file_append);
80 file_append = NULL;
81 file_append_size = 0;
82 file_updated = 0;
74} 83}
75 84
76static void __attribute__((noreturn)) 85static void __attribute__((noreturn))
@@ -92,12 +101,22 @@ succeed_file(void)
92static off_t 101static off_t
93ulseek(int const fd, off_t const offset, int const whence) 102ulseek(int const fd, off_t const offset, int const whence)
94{ 103{
95 off_t const w = lseek(fd, offset, whence); 104 switch (whence) {
96 if (w == (off_t)-1) { 105 case SEEK_SET:
97 perror("lseek"); 106 file_ptr = file_map + offset;
107 break;
108 case SEEK_CUR:
109 file_ptr += offset;
110 break;
111 case SEEK_END:
112 file_ptr = file_map + (sb.st_size - offset);
113 break;
114 }
115 if (file_ptr < file_map) {
116 fprintf(stderr, "lseek: seek before file\n");
98 fail_file(); 117 fail_file();
99 } 118 }
100 return w; 119 return file_ptr - file_map;
101} 120}
102 121
103static size_t 122static size_t
@@ -114,12 +133,38 @@ uread(int const fd, void *const buf, size_t const count)
114static size_t 133static size_t
115uwrite(int const fd, void const *const buf, size_t const count) 134uwrite(int const fd, void const *const buf, size_t const count)
116{ 135{
117 size_t const n = write(fd, buf, count); 136 size_t cnt = count;
118 if (n != count) { 137 off_t idx = 0;
119 perror("write"); 138
120 fail_file(); 139 file_updated = 1;
140
141 if (file_ptr + count >= file_end) {
142 off_t aoffset = (file_ptr + count) - file_end;
143
144 if (aoffset > file_append_size) {
145 file_append = realloc(file_append, aoffset);
146 file_append_size = aoffset;
147 }
148 if (!file_append) {
149 perror("write");
150 fail_file();
151 }
152 if (file_ptr < file_end) {
153 cnt = file_end - file_ptr;
154 } else {
155 cnt = 0;
156 idx = aoffset - count;
157 }
121 } 158 }
122 return n; 159
160 if (cnt)
161 memcpy(file_ptr, buf, cnt);
162
163 if (cnt < count)
164 memcpy(file_append + idx, buf + cnt, count - cnt);
165
166 file_ptr += count;
167 return count;
123} 168}
124 169
125static void * 170static void *
@@ -192,9 +237,7 @@ static int make_nop_arm64(void *map, size_t const offset)
192 */ 237 */
193static void *mmap_file(char const *fname) 238static void *mmap_file(char const *fname)
194{ 239{
195 void *addr; 240 fd_map = open(fname, O_RDONLY);
196
197 fd_map = open(fname, O_RDWR);
198 if (fd_map < 0 || fstat(fd_map, &sb) < 0) { 241 if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
199 perror(fname); 242 perror(fname);
200 fail_file(); 243 fail_file();
@@ -203,15 +246,58 @@ static void *mmap_file(char const *fname)
203 fprintf(stderr, "not a regular file: %s\n", fname); 246 fprintf(stderr, "not a regular file: %s\n", fname);
204 fail_file(); 247 fail_file();
205 } 248 }
206 addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, 249 file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
207 fd_map, 0); 250 fd_map, 0);
208 mmap_failed = 0; 251 mmap_failed = 0;
209 if (addr == MAP_FAILED) { 252 if (file_map == MAP_FAILED) {
210 mmap_failed = 1; 253 mmap_failed = 1;
211 addr = umalloc(sb.st_size); 254 file_map = umalloc(sb.st_size);
212 uread(fd_map, addr, sb.st_size); 255 uread(fd_map, file_map, sb.st_size);
256 }
257 close(fd_map);
258
259 file_end = file_map + sb.st_size;
260
261 return file_map;
262}
263
264static void write_file(const char *fname)
265{
266 char tmp_file[strlen(fname) + 4];
267 size_t n;
268
269 if (!file_updated)
270 return;
271
272 sprintf(tmp_file, "%s.rc", fname);
273
274 /*
275 * After reading the entire file into memory, delete it
276 * and write it back, to prevent weird side effects of modifying
277 * an object file in place.
278 */
279 fd_map = open(tmp_file, O_WRONLY | O_TRUNC | O_CREAT, sb.st_mode);
280 if (fd_map < 0) {
281 perror(fname);
282 fail_file();
283 }
284 n = write(fd_map, file_map, sb.st_size);
285 if (n != sb.st_size) {
286 perror("write");
287 fail_file();
288 }
289 if (file_append_size) {
290 n = write(fd_map, file_append, file_append_size);
291 if (n != file_append_size) {
292 perror("write");
293 fail_file();
294 }
295 }
296 close(fd_map);
297 if (rename(tmp_file, fname) < 0) {
298 perror(fname);
299 fail_file();
213 } 300 }
214 return addr;
215} 301}
216 302
217/* w8rev, w8nat, ...: Handle endianness. */ 303/* w8rev, w8nat, ...: Handle endianness. */
@@ -318,7 +404,6 @@ do_file(char const *const fname)
318 Elf32_Ehdr *const ehdr = mmap_file(fname); 404 Elf32_Ehdr *const ehdr = mmap_file(fname);
319 unsigned int reltype = 0; 405 unsigned int reltype = 0;
320 406
321 ehdr_curr = ehdr;
322 w = w4nat; 407 w = w4nat;
323 w2 = w2nat; 408 w2 = w2nat;
324 w8 = w8nat; 409 w8 = w8nat;
@@ -441,6 +526,7 @@ do_file(char const *const fname)
441 } 526 }
442 } /* end switch */ 527 } /* end switch */
443 528
529 write_file(fname);
444 cleanup(); 530 cleanup();
445} 531}
446 532
@@ -493,11 +579,14 @@ main(int argc, char *argv[])
493 case SJ_SETJMP: /* normal sequence */ 579 case SJ_SETJMP: /* normal sequence */
494 /* Avoid problems if early cleanup() */ 580 /* Avoid problems if early cleanup() */
495 fd_map = -1; 581 fd_map = -1;
496 ehdr_curr = NULL;
497 mmap_failed = 1; 582 mmap_failed = 1;
583 file_map = NULL;
584 file_ptr = NULL;
585 file_updated = 0;
498 do_file(file); 586 do_file(file);
499 break; 587 break;
500 case SJ_FAIL: /* error in do_file or below */ 588 case SJ_FAIL: /* error in do_file or below */
589 sprintf("%s: failed\n", file);
501 ++n_error; 590 ++n_error;
502 break; 591 break;
503 case SJ_SUCCEED: /* premature success */ 592 case SJ_SUCCEED: /* premature success */