In similar spirit to x86 and arm64 support, add a make_nop_arm() to replace calls to mcount with a "nop" in sections that aren't traced.
Cc: Russell King <li...@arm.linux.org.uk> Cc: Rabin Vincent <ra...@rab.in> Signed-off-by: Stephen Boyd <sb...@codeaurora.org> --- scripts/recordmcount.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ scripts/recordmcount.h | 3 ++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index e167592793a7..0b16d14c54fb 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -206,6 +206,52 @@ static int make_nop_x86(void *map, size_t const offset) return 0; } +/* + * Indicates if ARM is using __gnu_mcount_nc or mcount style and if + * we should replace it with a pop or a nop respectively. + */ +static int uses_altmcount; + +static unsigned char ideal_nop4_arm_arm[4] = { 0x00, 0x40, 0xbd, 0xe8 }; +static unsigned char ideal_nop4_arm_thumb[4] = { 0x5d, 0xf8, 0x04, 0xeb }; +static unsigned char ideal_nop4_arm_arm_be[4] = { 0xe8, 0xbd, 0x40, 0x00 }; +static unsigned char ideal_nop4_arm_thumb_be[4] = { 0xf8, 0x5d, 0xeb, 0x04 }; +static unsigned char ideal_nop4_arm_old[4] = { 0x00, 0x00, 0xa0, 0xe1 }; +static unsigned char ideal_nop4_arm_old_be[4] = { 0xe1, 0xa0, 0x00, 0x00 }; + +static unsigned char bl_gnu_mcount_nc_arm[4] = { 0xfe, 0xff, 0xff, 0xeb }; +static unsigned char bl_gnu_mcount_nc_thumb[4] = { 0xff, 0xf7, 0xfe, 0xff }; +static unsigned char bl_gnu_mcount_nc_arm_be[4] = { 0xeb, 0xff, 0xff, 0xfe }; +static unsigned char bl_gnu_mcount_nc_thumb_be[4] = { 0xf7, 0xff, 0xff, 0xfe }; + +static int make_nop_arm(void *map, size_t const offset) +{ + uint32_t *ptr; + + ptr = map + offset; + if (memcmp(ptr, bl_gnu_mcount_nc_arm, 4) == 0) { + if (uses_altmcount) + ideal_nop = ideal_nop4_arm_arm; + else + ideal_nop = ideal_nop4_arm_old; + } else if (memcmp(ptr, bl_gnu_mcount_nc_arm_be, 4) == 0) { + if (uses_altmcount) + ideal_nop = ideal_nop4_arm_arm_be; + else + ideal_nop = ideal_nop4_arm_old_be; + } else if (memcmp(ptr, bl_gnu_mcount_nc_thumb, 4) == 0) + ideal_nop = ideal_nop4_arm_thumb; + else if (memcmp(ptr, bl_gnu_mcount_nc_thumb_be, 4) == 0) + ideal_nop = ideal_nop4_arm_thumb_be; + else + return -1; + + /* Convert to nop */ + ulseek(fd_map, offset, SEEK_SET); + uwrite(fd_map, ideal_nop, 4); + return 0; +} + static unsigned char ideal_nop4_arm64[4] = {0x1f, 0x20, 0x03, 0xd5}; static int make_nop_arm64(void *map, size_t const offset) { @@ -454,6 +500,9 @@ do_file(char const *const fname) break; case EM_ARM: reltype = R_ARM_ABS32; altmcount = "__gnu_mcount_nc"; + make_nop = make_nop_arm; + rel_type_nop = R_ARM_NONE; + ideal_nop = ideal_nop4_arm_arm; break; case EM_AARCH64: reltype = R_AARCH64_ABS64; diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index b9897e2be404..890f5211745f 100644 --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h @@ -266,7 +266,8 @@ static unsigned get_mcountsym(Elf_Sym const *const sym0, if (symname[0] == '.') ++symname; /* ppc64 hack */ if (strcmp(mcount, symname) == 0 || - (altmcount && strcmp(altmcount, symname) == 0) || + (altmcount && strcmp(altmcount, symname) == 0 && + (uses_altmcount = 1)) || (strcmp(fentry, symname) == 0)) mcountsym = Elf_r_sym(relp); -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project