2

I am in a situation in an embedded system (an xtensa processor) where I need to manually override a symbol, but the symbol happens to be in the middle of another symbol. When I try using -Wl,--wrap=symbol it won't work, since the symbol isn't its own thing.

What I need to do is specify (preferably in a GCC .S, though .c is okay) where the code will end up. Though the actual symbol will be located somewhere random by the compiler, I will be memcpying the code into the correct place.

40101388 <replacement_user_vect>: 40101388: 13d100 wsr.excsave1 a0 4010138b: 002020 esync 4010138e: 011fc5 call0 4010258c <_UserExceptionVector_1>

My problem is GCC creates the assembly with relative jumps assuming the code will be located where it is in flash, while the eventual location will be fixed in an interrupt vector. How do I tell GCC / GNU as "put the code wherever you feel like, but, trust me it will actually execute from {here}"

Though my code is at 0x40101388 (GCC decided) it will eventually reside and execute from 0x40100050. How do I trick GCC by telling it "put the code HERE" but pretend it's located "HERE"

EDIT: I was able to get around this, as it turns out, the function I needed to modify was held in the linker script, individually. I was able to just switch it out in the linker script. Though I still would love to know the answer, I now have a work-around.

Charles Lohr
  • 695
  • 1
  • 8
  • 23
  • 1
    gcc or gas do not relocate any code. They are not linkers. And **relative** jumps are position-independent by definition. Not clear what your problem is (and what "in the middle of another symbol" means). See [ask], provide sufficient information. – too honest for this site Aug 12 '16 at 01:19
  • You can define in ```as``` a specific symbol, that is to appear somewhere in code. The linker cannot relocate that, but I'm not sure why. You can seem to relocate symbols that are completely independent things like functions in my tests, but it wouldn't relocate if it saw something in the middle of a function. Not sure why. – Charles Lohr Aug 12 '16 at 01:26
  • 4
    Your first paragraph makes no sense, but if I ignore that then you can do what you want by putting the code you want to copy somewhere else in it's own section and then using a linker script to tell the linker where it will be copied to. It seems the Linux kernel does exactly that see the`SECTION_VECTOR` macro in http://lxr.free-electrons.com/source/arch/xtensa/kernel/vmlinux.lds.S – Ross Ridge Aug 12 '16 at 05:17
  • Can't you instead modify the vector table to point to your symbol? I find it weird you can copy something at `0x40100050` without some sort of damage, but you can't specify content of that in executable directly. Or is there system/default code at `0x40100050`, and your code is loaded later elsewhere? As jmp/call are relative, as long as you copy all the code required to `0x40100050`, it should work as is. In old assemblers there was `org` directive to produce machine code designed for particular address, but in `as` the `.org` is more complicated (I think it will not help you). – Ped7g Aug 12 '16 at 11:15
  • I normally would do that, but on xtensa, there is no truly "long call/jump" Any non-relative asm operation is awfully slow. What I really need is a true .org that only effects code creation, not placement. – Charles Lohr Aug 12 '16 at 12:07
  • 1
    I'm still missing the point, what is your problem. 1) as all your code already is relative, you can copy it all to `0x40100050` (unless it's too long to fit there). 2) where the `0x40100050` comes from? Isn't it from some vector-handler table? So why don't you modify the table to set up new handler at your address, forgetting about `0x40100050`? 3) if you would put that handler into separate `.section` and modify linkscript to land that section at `0x40100050`, will it do? Is that part of code fetched from flash rom too? etc... Is your problem is that `call0 4010258c`? Copy that code too then. – Ped7g Aug 12 '16 at 16:42

1 Answers1

5

In the linker script each output section has two associated addresses: VMA and LMA -- the address for which the code is linked and the address where the code will be loaded.

Put the code that needs to be relocated into separate section, add an output section to your linker script with desired VMA and LMA and put an input section matching the name of the code section inside it.

E.g. the following C code

void f(void) __attribute__((section(".relocatable1.text")))
{
    ...
}

extern char _relocatable1_lma[];
extern char _relocatable1_vma_start[];
extern char _relocatable1_vma_end[];

void relocatable1_copy(void)
{
        memcpy(_relocatable1_vma_start, _relocatable1_lma,
               _relocatable1_vma_end - _relocatable1_vma_start);
}

Together with the following piece of ld script, with VMA substituted with the desired target code location

SECTIONS {
  ...
  .some_section : { ... }
  .relocatable1 VMA : AT(LOADADDR(.some_section) + SIZEOF(.some_section)) {
    _relocatable1_vma_start = . ;
    *(.relocatable1.literal .relocatable1.text) ;
    _relocatable1_vma_end = . ;
  }
  _relocatable1_lma = LOADADDR(.relocatable1) ;
  ...
}

should do what you want.

jcmvbkbc
  • 723
  • 1
  • 4
  • 5