aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scripts/recordmcount.c548
-rw-r--r--scripts/recordmcount.h366
2 files changed, 370 insertions, 544 deletions
diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c
index 34f32be17090..7f7f7180fe24 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -212,550 +212,10 @@ is_mcounted_section_name(char const *const txtname)
212 0 == strcmp(".text.unlikely", txtname); 212 0 == strcmp(".text.unlikely", txtname);
213} 213}
214 214
215/* Append the new shstrtab, Elf32_Shdr[], __mcount_loc and its relocations. */ 215/* 32 bit and 64 bit are very similar */
216static void append32(Elf32_Ehdr *const ehdr, 216#include "recordmcount.h"
217 Elf32_Shdr *const shstr, 217#define RECORD_MCOUNT_64
218 uint32_t const *const mloc0, 218#include "recordmcount.h"
219 uint32_t const *const mlocp,
220 Elf32_Rel const *const mrel0,
221 Elf32_Rel const *const mrelp,
222 unsigned int const rel_entsize,
223 unsigned int const symsec_sh_link)
224{
225 /* Begin constructing output file */
226 Elf32_Shdr mcsec;
227 char const *mc_name = (sizeof(Elf32_Rela) == rel_entsize)
228 ? ".rela__mcount_loc"
229 : ".rel__mcount_loc";
230 unsigned const old_shnum = w2(ehdr->e_shnum);
231 uint32_t const old_shoff = w(ehdr->e_shoff);
232 uint32_t const old_shstr_sh_size = w(shstr->sh_size);
233 uint32_t const old_shstr_sh_offset = w(shstr->sh_offset);
234 uint32_t t = 1 + strlen(mc_name) + w(shstr->sh_size);
235 uint32_t new_e_shoff;
236
237 shstr->sh_size = w(t);
238 shstr->sh_offset = w(sb.st_size);
239 t += sb.st_size;
240 t += (3u & -t); /* 4-byte align */
241 new_e_shoff = t;
242
243 /* body for new shstrtab */
244 ulseek(fd_map, sb.st_size, SEEK_SET);
245 uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
246 uwrite(fd_map, mc_name, 1 + strlen(mc_name));
247
248 /* old(modified) Elf32_Shdr table, 4-byte aligned */
249 ulseek(fd_map, t, SEEK_SET);
250 t += sizeof(Elf32_Shdr) * old_shnum;
251 uwrite(fd_map, old_shoff + (void *)ehdr,
252 sizeof(Elf32_Shdr) * old_shnum);
253
254 /* new sections __mcount_loc and .rel__mcount_loc */
255 t += 2*sizeof(mcsec);
256 mcsec.sh_name = w((sizeof(Elf32_Rela) == rel_entsize) + strlen(".rel")
257 + old_shstr_sh_size);
258 mcsec.sh_type = w(SHT_PROGBITS);
259 mcsec.sh_flags = w(SHF_ALLOC);
260 mcsec.sh_addr = 0;
261 mcsec.sh_offset = w(t);
262 mcsec.sh_size = w((void *)mlocp - (void *)mloc0);
263 mcsec.sh_link = 0;
264 mcsec.sh_info = 0;
265 mcsec.sh_addralign = w(4);
266 mcsec.sh_entsize = w(4);
267 uwrite(fd_map, &mcsec, sizeof(mcsec));
268
269 mcsec.sh_name = w(old_shstr_sh_size);
270 mcsec.sh_type = (sizeof(Elf32_Rela) == rel_entsize)
271 ? w(SHT_RELA)
272 : w(SHT_REL);
273 mcsec.sh_flags = 0;
274 mcsec.sh_addr = 0;
275 mcsec.sh_offset = w((void *)mlocp - (void *)mloc0 + t);
276 mcsec.sh_size = w((void *)mrelp - (void *)mrel0);
277 mcsec.sh_link = w(symsec_sh_link);
278 mcsec.sh_info = w(old_shnum);
279 mcsec.sh_addralign = w(4);
280 mcsec.sh_entsize = w(rel_entsize);
281 uwrite(fd_map, &mcsec, sizeof(mcsec));
282
283 uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
284 uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
285
286 ehdr->e_shoff = w(new_e_shoff);
287 ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */
288 ulseek(fd_map, 0, SEEK_SET);
289 uwrite(fd_map, ehdr, sizeof(*ehdr));
290}
291
292/*
293 * append64 and append32 (and other analogous pairs) could be templated
294 * using C++, but the complexity is high. (For an example, look at p_elf.h
295 * in the source for UPX, http://upx.sourceforge.net) So: remember to make
296 * the corresponding change in the routine for the other size.
297 */
298static void append64(Elf64_Ehdr *const ehdr,
299 Elf64_Shdr *const shstr,
300 uint64_t const *const mloc0,
301 uint64_t const *const mlocp,
302 Elf64_Rel const *const mrel0,
303 Elf64_Rel const *const mrelp,
304 unsigned int const rel_entsize,
305 unsigned int const symsec_sh_link)
306{
307 /* Begin constructing output file */
308 Elf64_Shdr mcsec;
309 char const *mc_name = (sizeof(Elf64_Rela) == rel_entsize)
310 ? ".rela__mcount_loc"
311 : ".rel__mcount_loc";
312 unsigned const old_shnum = w2(ehdr->e_shnum);
313 uint64_t const old_shoff = w8(ehdr->e_shoff);
314 uint64_t const old_shstr_sh_size = w8(shstr->sh_size);
315 uint64_t const old_shstr_sh_offset = w8(shstr->sh_offset);
316 uint64_t t = 1 + strlen(mc_name) + w8(shstr->sh_size);
317 uint64_t new_e_shoff;
318
319 shstr->sh_size = w8(t);
320 shstr->sh_offset = w8(sb.st_size);
321 t += sb.st_size;
322 t += (7u & -t); /* 8-byte align */
323 new_e_shoff = t;
324
325 /* body for new shstrtab */
326 ulseek(fd_map, sb.st_size, SEEK_SET);
327 uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
328 uwrite(fd_map, mc_name, 1 + strlen(mc_name));
329
330 /* old(modified) Elf64_Shdr table, 8-byte aligned */
331 ulseek(fd_map, t, SEEK_SET);
332 t += sizeof(Elf64_Shdr) * old_shnum;
333 uwrite(fd_map, old_shoff + (void *)ehdr,
334 sizeof(Elf64_Shdr) * old_shnum);
335
336 /* new sections __mcount_loc and .rel__mcount_loc */
337 t += 2*sizeof(mcsec);
338 mcsec.sh_name = w((sizeof(Elf64_Rela) == rel_entsize) + strlen(".rel")
339 + old_shstr_sh_size);
340 mcsec.sh_type = w(SHT_PROGBITS);
341 mcsec.sh_flags = w8(SHF_ALLOC);
342 mcsec.sh_addr = 0;
343 mcsec.sh_offset = w8(t);
344 mcsec.sh_size = w8((void *)mlocp - (void *)mloc0);
345 mcsec.sh_link = 0;
346 mcsec.sh_info = 0;
347 mcsec.sh_addralign = w8(8);
348 mcsec.sh_entsize = w8(8);
349 uwrite(fd_map, &mcsec, sizeof(mcsec));
350
351 mcsec.sh_name = w(old_shstr_sh_size);
352 mcsec.sh_type = (sizeof(Elf64_Rela) == rel_entsize)
353 ? w(SHT_RELA)
354 : w(SHT_REL);
355 mcsec.sh_flags = 0;
356 mcsec.sh_addr = 0;
357 mcsec.sh_offset = w8((void *)mlocp - (void *)mloc0 + t);
358 mcsec.sh_size = w8((void *)mrelp - (void *)mrel0);
359 mcsec.sh_link = w(symsec_sh_link);
360 mcsec.sh_info = w(old_shnum);
361 mcsec.sh_addralign = w8(8);
362 mcsec.sh_entsize = w8(rel_entsize);
363 uwrite(fd_map, &mcsec, sizeof(mcsec));
364
365 uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
366 uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
367
368 ehdr->e_shoff = w8(new_e_shoff);
369 ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */
370 ulseek(fd_map, 0, SEEK_SET);
371 uwrite(fd_map, ehdr, sizeof(*ehdr));
372}
373
374/*
375 * Look at the relocations in order to find the calls to mcount.
376 * Accumulate the section offsets that are found, and their relocation info,
377 * onto the end of the existing arrays.
378 */
379static uint32_t *sift32_rel_mcount(uint32_t *mlocp,
380 unsigned const offbase,
381 Elf32_Rel **const mrelpp,
382 Elf32_Shdr const *const relhdr,
383 Elf32_Ehdr const *const ehdr,
384 unsigned const recsym,
385 uint32_t const recval,
386 unsigned const reltype)
387{
388 uint32_t *const mloc0 = mlocp;
389 Elf32_Rel *mrelp = *mrelpp;
390 Elf32_Shdr *const shdr0 = (Elf32_Shdr *)(w(ehdr->e_shoff)
391 + (void *)ehdr);
392 unsigned const symsec_sh_link = w(relhdr->sh_link);
393 Elf32_Shdr const *const symsec = &shdr0[symsec_sh_link];
394 Elf32_Sym const *const sym0 = (Elf32_Sym const *)(w(symsec->sh_offset)
395 + (void *)ehdr);
396
397 Elf32_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
398 char const *const str0 = (char const *)(w(strsec->sh_offset)
399 + (void *)ehdr);