aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/recordmcount.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-10-13 19:06:14 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-10-14 16:54:00 -0400
commitc28d5077f8d79bfce1e3f88db2e261cf2b6473dc (patch)
treec291f156e75beb02dfa5615a7040a549912dd8ba /scripts/recordmcount.c
parent72441cb1fd77d092f09ddfac748955703884c9a7 (diff)
ftrace: Remove duplicate code for 64 and 32 bit in recordmcount.c
The elf reader for recordmcount.c had duplicate functions for both 32 bit and 64 bit elf handling. This was due to the need of using the 32 and 64 bit elf structures. This patch consolidates the two by using macros to define the 32 and 64 bit names in a recordmcount.h file, and then by just defining a RECORD_MCOUNT_64 macro and including recordmcount.h twice we create the funtions for both the 32 bit version as well as the 64 bit version using one code source. Cc: John Reiser <jreiser@bitwagon.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'scripts/recordmcount.c')
-rw-r--r--scripts/recordmcount.c548
1 files changed, 4 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);
400
401 Elf32_Rel const *const rel0 = (Elf32_Rel const *)(w(relhdr->sh_offset)
402 + (void *)ehdr);
403 unsigned rel_entsize = w(relhdr->sh_entsize);
404 unsigned const nrel = w(relhdr->sh_size) / rel_entsize;
405 Elf32_Rel const *relp = rel0;
406
407 unsigned mcountsym = 0;
408 unsigned t;
409
410 for (t = nrel; t; --t) {
411 if (!mcountsym) {
412 Elf32_Sym const *const symp =
413 &sym0[ELF32_R_SYM(w(relp->r_info))];
414
415 if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
416 &str0[w(symp->st_name)]))
417 mcountsym = ELF32_R_SYM(w(relp->r_info));
418 }
419 if (mcountsym == ELF32_R_SYM(w(relp->r_info))) {
420 uint32_t const addend = w(w(relp->r_offset) - recval);
421 mrelp->r_offset = w(offbase
422 + ((void *)mlocp - (void *)mloc0));
423 mrelp->r_info = w(ELF32_R_INFO(recsym, reltype));
424 if (sizeof(Elf32_Rela) == rel_entsize) {
425 ((Elf32_Rela *)mrelp)->r_addend = addend;
426 *mlocp++ = 0;
427 } else
428 *mlocp++ = addend;
429
430 mrelp = (Elf32_Rel *)(rel_entsize + (void *)mrelp);
431 }
432 relp = (Elf32_Rel const *)(rel_entsize + (void *)relp);
433 }
434 *mrelpp = mrelp;
435 return mlocp;
436}
437
438static uint64_t *sift64_rel_mcount(uint64_t *mlocp,
439 unsigned const offbase,
440 Elf64_Rel **const mrelpp,
441 Elf64_Shdr const *const relhdr,
442 Elf64_Ehdr const *const ehdr,
443 unsigned const recsym,
444 uint64_t const recval,
445 unsigned const reltype)
446{
447 uint64_t *const mloc0 = mlocp;
448 Elf64_Rel *mrelp = *mrelpp;
449 Elf64_Shdr *const shdr0 = (Elf64_Shdr *)(w8(ehdr->e_shoff)
450 + (void *)ehdr);
451 unsigned const symsec_sh_link = w(relhdr->sh_link);
452 Elf64_Shdr const *const symsec = &shdr0[symsec_sh_link];
453 Elf64_Sym const *const sym0 = (Elf64_Sym const *)(w8(symsec->sh_offset)
454 + (void *)ehdr);
455
456 Elf64_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
457 char const *const str0 = (char const *)(w8(strsec->sh_offset)
458 + (void *)ehdr);
459
460 Elf64_Rel const *const rel0 = (Elf64_Rel const *)(w8(relhdr->sh_offset)
461 + (void *)ehdr);
462 unsigned rel_entsize = w8(relhdr->sh_entsize);
463 unsigned const nrel = w8(relhdr->sh_size) / rel_entsize;
464 Elf64_Rel const *relp = rel0;
465
466 unsigned mcountsym = 0;
467 unsigned t;
468
469 for (t = nrel; 0 != t; --t) {
470 if (!mcountsym) {
471 Elf64_Sym const *const symp =
472 &sym0[ELF64_R_SYM(w8(relp->r_info))];
473 char const *symname = &str0[w(symp->st_name)];
474
475 if ('.' == symname[0])
476 ++symname; /* ppc64 hack */
477 if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
478 symname))
479 mcountsym = ELF64_R_SYM(w8(relp->r_info));
480 }
481
482 if (mcountsym == ELF64_R_SYM(w8(relp->r_info))) {
483 uint64_t const addend = w8(w8(relp->r_offset) - recval);
484
485 mrelp->r_offset = w8(offbase
486 + ((void *)mlocp - (void *)mloc0));
487 mrelp->r_info = w8(ELF64_R_INFO(recsym, reltype));
488 if (sizeof(Elf64_Rela) == rel_entsize) {
489 ((Elf64_Rela *)mrelp)->r_addend = addend;
490 *mlocp++ = 0;
491 } else
492 *mlocp++ = addend;
493
494 mrelp = (Elf64_Rel *)(rel_entsize + (void *)mrelp);
495 }
496 relp = (Elf64_Rel const *)(rel_entsize + (void *)relp);
497 }
498 *mrelpp = mrelp;
499
500 return mlocp;
501}
502
503/*
504 * Find a symbol in the given section, to be used as the base for relocating
505 * the table of offsets of calls to mcount. A local or global symbol suffices,
506 * but avoid a Weak symbol because it may be overridden; the change in value
507 * would invalidate the relocations of the offsets of the calls to mcount.
508 * Often the found symbol will be the unnamed local symbol generated by
509 * GNU 'as' for the start of each section. For example:
510 * Num: Value Size Type Bind Vis Ndx Name
511 * 2: 00000000 0 SECTION LOCAL DEFAULT 1
512 */
513static unsigned find32_secsym_ndx(unsigned const txtndx,
514 char const *const txtname,
515 uint32_t *const recvalp,
516 Elf32_Shdr const *const symhdr,
517 Elf32_Ehdr const *const ehdr)
518{
519 Elf32_Sym const *const sym0 = (Elf32_Sym const *)(w(symhdr->sh_offset)
520 + (void *)ehdr);
521 unsigned const nsym = w(symhdr->sh_size) / w(symhdr->sh_entsize);
522 Elf32_Sym const *symp;
523 unsigned t;
524
525 for (symp = sym0, t = nsym; t; --t, ++symp) {
526 unsigned int const st_bind = ELF32_ST_BIND(symp->st_info);
527
528 if (txtndx == w2(symp->st_shndx)
529 /* avoid STB_WEAK */
530 && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
531 *recvalp = w(symp->st_value);
532 return symp - sym0;
533 }
534 }
535 fprintf(stderr, "Cannot find symbol for section %d: %s.\n",
536 txtndx, txtname);
537 fail_file();
538}
539
540static unsigned find64_secsym_ndx(unsigned const txtndx,
541 char const *const txtname,
542 uint64_t *const recvalp,
543 Elf64_Shdr const *const symhdr,
544 Elf64_Ehdr const *const ehdr)
545{
546 Elf64_Sym const *const sym0 = (Elf64_Sym const *)(w8(symhdr->sh_offset)
547 + (void *)ehdr);
548 unsigned const nsym = w8(symhdr->sh_size) / w8(symhdr->sh_entsize);
549 Elf64_Sym const *symp;
550 unsigned t;
551
552 for (symp = sym0, t = nsym; t; --t, ++symp) {
553 unsigned int const st_bind = ELF64_ST_BIND(symp->st_info);
554
555 if (txtndx == w2(symp->st_shndx)
556 /* avoid STB_WEAK */
557 && (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
558 *recvalp = w8(symp->st_value);
559 return symp - sym0;
560 }
561 }
562 fprintf(stderr, "Cannot find symbol for section %d: %s.\n",
563 txtndx, txtname);
564 fail_file();
565}
566
567/*
568 * Evade ISO C restriction: no declaration after statement in
569 * has32_rel_mcount.
570 */
571static char const *
572__has32_rel_mcount(Elf32_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
573 Elf32_Shdr const *const shdr0,
574 char const *const shstrtab,
575 char const *const fname)
576{
577 /* .sh_info depends on .sh_type == SHT_REL[,A] */
578 Elf32_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
579 char const *const txtname = &shstrtab[w(txthdr->sh_name)];
580
581 if (0 == strcmp("__mcount_loc", txtname)) {
582 fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
583 fname);
584 succeed_file();
585 }
586 if (SHT_PROGBITS != w(txthdr->sh_type) ||
587 !is_mcounted_section_name(txtname))
588 return NULL;
589 return txtname;
590}
591
592static char const *has32_rel_mcount(Elf32_Shdr const *const relhdr,
593 Elf32_Shdr const *const shdr0,
594 char const *const shstrtab,
595 char const *const fname)
596{
597 if (SHT_REL != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type))
598 return NULL;
599 return __has32_rel_mcount(relhdr, shdr0, shstrtab, fname);
600}
601
602static char const *__has64_rel_mcount(Elf64_Shdr const *const relhdr,
603 Elf64_Shdr const *const shdr0,
604 char const *const shstrtab,
605 char const *const fname)
606{
607 /* .sh_info depends on .sh_type == SHT_REL[,A] */
608 Elf64_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
609 char const *const txtname = &shstrtab[w(txthdr->sh_name)];
610
611 if (0 == strcmp("__mcount_loc", txtname)) {
612 fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
613 fname);
614 succeed_file();
615 }
616 if (SHT_PROGBITS != w(txthdr->sh_type) ||
617 !is_mcounted_section_name(txtname))
618 return NULL;
619 return txtname;
620}
621
622static char const *has64_rel_mcount(Elf64_Shdr const *const relhdr,
623 Elf64_Shdr const *const shdr0,
624 char const *const shstrtab,
625 char const *const fname)
626{
627 if (SHT_REL != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type))
628 return NULL;
629 return __has64_rel_mcount(relhdr, shdr0, shstrtab, fname);
630}
631
632static unsigned tot32_relsize(Elf32_Shdr const *const shdr0,
633 unsigned nhdr,
634 const char *const shstrtab,
635 const char *const fname)
636{
637 unsigned totrelsz = 0;
638 Elf32_Shdr const *shdrp = shdr0;
639 for (; 0 != nhdr; --nhdr, ++shdrp) {
640 if (has32_rel_mcount(shdrp, shdr0, shstrtab, fname))
641 totrelsz += w(shdrp->sh_size);
642 }
643 return totrelsz;
644}
645
646static unsigned tot64_relsize(Elf64_Shdr const *const shdr0,
647 unsigned nhdr,
648 const char *const shstrtab,
649 const char *const fname)
650{
651 unsigned totrelsz = 0;
652 Elf64_Shdr const *shdrp = shdr0;
653
654 for (; nhdr; --nhdr, ++shdrp) {
655 if (has64_rel_mcount(shdrp, shdr0, shstrtab, fname))
656 totrelsz += w8(shdrp->sh_size);
657 }
658 return totrelsz;
659}
660
661/* Overall supervision for Elf32 ET_REL file. */
662static void
663do32(Elf32_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
664{
665 Elf32_Shdr *const shdr0 = (Elf32_Shdr *)(w(ehdr->e_shoff)
666 + (void *)ehdr);
667 unsigned const nhdr = w2(ehdr->e_shnum);
668 Elf32_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)];
669 char const *const shstrtab = (char const *)(w(shstr->sh_offset)
670 + (void *)ehdr);
671
672 Elf32_Shdr const *relhdr;
673 unsigned k;
674
675 /* Upper bound on space: assume all relevant relocs are for mcount. */
676 unsigned const totrelsz = tot32_relsize(shdr0, nhdr, shstrtab, fname);
677 Elf32_Rel *const mrel0 = umalloc(totrelsz);
678 Elf32_Rel * mrelp = mrel0;
679
680 /* 2*sizeof(address) <= sizeof(Elf32_Rel) */
681 uint32_t *const mloc0 = umalloc(totrelsz>>1);
682 uint32_t * mlocp = mloc0;
683
684 unsigned rel_entsize = 0;
685 unsigned symsec_sh_link = 0;
686
687 for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
688 char const *const txtname = has32_rel_mcount(relhdr, shdr0,
689 shstrtab, fname);
690 if (txtname) {
691 uint32_t recval = 0;
692 unsigned const recsym = find32_secsym_ndx(
693 w(relhdr->sh_info), txtname, &recval,
694 &shdr0[symsec_sh_link = w(relhdr->sh_link)],
695 ehdr);
696
697 rel_entsize = w(relhdr->sh_entsize);
698 mlocp = sift32_rel_mcount(mlocp,
699 (void *)mlocp - (void *)mloc0, &mrelp,
700 relhdr, ehdr, recsym, recval, reltype);
701 }
702 }
703 if (mloc0 != mlocp) {
704 append32(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
705 rel_entsize, symsec_sh_link);
706 }
707 free(mrel0);
708 free(mloc0);
709}
710
711static void
712do64(Elf64_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
713{
714 Elf64_Shdr *const shdr0 = (Elf64_Shdr *)(w8(ehdr->e_shoff)
715 + (void *)ehdr);
716 unsigned const nhdr = w2(ehdr->e_shnum);
717 Elf64_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)];
718 char const *const shstrtab = (char const *)(w8(shstr->sh_offset)
719 + (void *)ehdr);
720
721 Elf64_Shdr const *relhdr;
722 unsigned k;
723
724 /* Upper bound on space: assume all relevant relocs are for mcount. */
725 unsigned const totrelsz = tot64_relsize(shdr0, nhdr, shstrtab, fname);
726 Elf64_Rel *const mrel0 = umalloc(totrelsz);
727 Elf64_Rel * mrelp = mrel0;
728
729 /* 2*sizeof(address) <= sizeof(Elf64_Rel) */
730 uint64_t *const mloc0 = umalloc(totrelsz>>1);
731 uint64_t * mlocp = mloc0;
732
733 unsigned rel_entsize = 0;
734 unsigned symsec_sh_link = 0;
735
736 for ((relhdr = shdr0), k = nhdr; k; --k, ++relhdr) {
737 char const *const txtname = has64_rel_mcount(relhdr, shdr0,
738 shstrtab, fname);
739 if (txtname) {
740 uint64_t recval = 0;
741 unsigned const recsym = find64_secsym_ndx(
742 w(relhdr->sh_info), txtname, &recval,
743 &shdr0[symsec_sh_link = w(relhdr->sh_link)],
744 ehdr);
745
746 rel_entsize = w8(relhdr->sh_entsize);
747 mlocp = sift64_rel_mcount(mlocp,
748 (void *)mlocp - (void *)mloc0, &mrelp,
749 relhdr, ehdr, recsym, recval, reltype);
750 }
751 }
752 if (mloc0 != mlocp) {
753 append64(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
754 rel_entsize, symsec_sh_link);
755 }
756 free(mrel0);
757 free(mloc0);
758}
759 219
760static void 220static void
761do_file(char const *const fname) 221do_file(char const *const fname)