2016-08-12 7 views
1

У меня возникла ситуация во встроенной системе (процессор xtensa), где мне нужно вручную переопределить символ, но символ находится в середине другого символа. Когда я пытаюсь использовать -Wl,--wrap=symbol, он не будет работать, поскольку символ не является его собственностью.Как указать перемещение вручную для кода GCC?

Что мне нужно сделать, это указать (желательно в GCC .S, хотя .c в порядке), где код будет в конечном итоге. Хотя фактический символ будет размещен где-то случайно компилятором, я буду memcpy код в нужном месте.

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

Моя проблема заключается в GCC создает сборку с относительными скачками, предполагающих коды будут находиться где вспышка, в то время как в конечном итоге место будет исправлены в векторе прерывания. Как сообщить GCC/GNU, что «введите код, где бы вы ни находились, но, поверьте мне, он действительно выполнится из {здесь}»

Хотя мой код находится на 0x40101388 (GCC решил), он в конечном итоге будет проживать и выполнять от 0x40100050. Как обмануть GCC, говоря это «поставить код здесь», но делать вид, что находится «здесь»

EDIT: Я был в состоянии обойти это, как выясняется, функции мне нужно, чтобы изменить проходил в сценарии компоновщика, индивидуально. Я смог просто переключить его в сценарии компоновщика. Хотя мне все же хотелось бы узнать ответ, теперь у меня есть обход.

+1

gcc или газ не перекладывают код. Они не являются линкерами. А ** относительные ** прыжки по определению не зависят от позиции. Неясно, какова ваша проблема (и что означает «в середине другого символа»). См. [Ask], укажите достаточную информацию. – Olaf

+0

Вы можете определить в '' 'как' '' определенный символ, который должен появиться где-то в коде. Линкер не может переместить это, но я не уверен, почему. Кажется, вы перемещаете символы, которые являются полностью независимыми вещами, такими как функции в моих тестах, но они не будут перемещаться, если он увидит что-то посредине функции. Не знаю, почему. –

+4

Ваш первый абзац не имеет смысла, но если я проигнорирую это, тогда вы можете сделать то, что хотите, поставив код, который хотите скопировать где-то еще в своем собственном разделе, а затем с помощью сценария компоновщика, чтобы сообщить компоновщику, где он будет скопирован в , Кажется, что ядро ​​Linux делает именно то, что видит макрос 'SECTION_VECTOR' в http://lxr.free-electrons.com/source/arch/xtensa/kernel/vmlinux.lds.S –

ответ

3

В сценарии компоновщика каждый выходной раздел имеет два связанных адреса: VMA и LMA - адрес, для которого связан код, и адрес, в котором будет загружен код.

Поместите код, который необходимо переместить в отдельный раздел, добавьте раздел вывода к сценарию компоновщика с желаемыми VMA и LMA и поместите раздел ввода, соответствующий имени секции кода внутри него.

E.g. следующий код C

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); 
} 

вместе со следующим куском Л.Д. сценария, с VMA замещенным с требуемым целевым кодом местоположения

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) ; 
    ... 
} 

должны делать то, что вы хотите.

 Смежные вопросы

  • Нет связанных вопросов^_^