From e571850d794c46b55f1a0fb0ffb22d594bee1d69 Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sun, 2 Feb 2014 17:15:19 +0800 Subject: [PATCH] Add support of Thumb to ARM branch relocation --- Changelog | 1 + tccelf.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Changelog b/Changelog index 966375d..b7ddd42 100644 --- a/Changelog +++ b/Changelog @@ -67,6 +67,7 @@ Bug fixes: - fix negation of 0.0 and -0.0 values (Thomas Preud'homme) - fix integer to double conversion on ARM (Thomas Preud'homme) - fix parameter passing of (unsigned) long long bitfield (Thomas Preud'homme) +- fix relocation of Thumb branch to ARM function (Thomas Preud'homme) version 0.9.26: diff --git a/tccelf.c b/tccelf.c index 66462c2..bae8972 100644 --- a/tccelf.c +++ b/tccelf.c @@ -1188,6 +1188,34 @@ ST_FUNC void build_got_entries(TCCState *s1) sym_index); } break; + case R_ARM_THM_JUMP24: + sym_index = ELFW(R_SYM)(rel->r_info); + sym = &((ElfW(Sym) *)symtab_section->data)[sym_index]; + /* We are relocating a jump from thumb code to arm code */ + if (sym->st_shndx != SHN_UNDEF && !(sym->st_value & 1)) { + int index; + uint8_t *p; + char *name, buf[1024]; + Section *text_section; + + name = symtab_section->link->data + sym->st_name; + text_section = s1->sections[sym->st_shndx]; + /* Modify reloc to target a thumb stub to switch to ARM */ + snprintf(buf, sizeof(buf), "%s_from_thumb", name); + index = put_elf_sym(symtab_section, + text_section->data_offset + 1, + sym->st_size, sym->st_info, 0, + sym->st_shndx, buf); + rel->r_info = ELFW(R_INFO)(index, type); + /* Create a thumb stub fonction to switch to ARM mode */ + put_elf_reloc(symtab_section, text_section, + text_section->data_offset, R_ARM_JUMP24, + sym_index); + p = section_ptr_add(text_section, 8); + put32(p, 0x4778); /* bx pc */ + put32(p+2, 0x46c0); /* nop */ + put32(p+4, 0xeafffffe); /* b $sym */ + } #elif defined(TCC_TARGET_C67) case R_C60_GOT32: case R_C60_GOTOFF: