почему я не могу заставить ld использовать точку входа, отличную от значения по умолчанию, с ld -e
Вы можете это сделать.Это:
int foo(int argc, char *argv[]) { return 0; }
gcc main.c -Wl,-e,foo
не будет работать, потому что выполнение не начинается с main.Он начинается с _start
, который связан с crt0.o
(часть glibc) и обеспечивает правильную работу таких вещей, как динамическое связывание и т. Д.Перенаправив _start
на foo
, вы обошли все, что требовалось для инициализации glibc, и поэтому все не работает.
Но если вам не нужны динамические ссылки, и вы готовы делать то, что нужноGlibc обычно делает для вас, тогда вы можете назвать точку входа как хотите.Пример:
#include <syscall.h>
int foo()
{
syscall(SYS_write, 1, "Hello, world\n", 13);
syscall(SYS_exit, 0);
}
gcc t.c -static -nostartfiles -Wl,-e,foo && ./a.out
Hello, world
Да, и ваш заголовок этого вопроса не соответствует вашему фактическому вопросу (плохая идея (TM)).
Чтобы ответить на вопрос в заголовке, вы уверены, что может изменить адрес, с которым связан ваш исполняемый файл.По умолчанию вы получаете 0x8048000
адрес загрузки (только в 32-битном режиме; 64-битный по умолчанию 0x400000
).
Вы можете легко изменить его, например, на 0x80000
, добавив -Wl,-Ttext-segment=0x80000
кстрока ссылки.
Обновление:
Однако, когда я пытаюсь установить связь с программой ld -N -e0x400082 -Ttext = 0x400082 program.o -o (перемещение сегмента текста и точки входана 4 байта), программа будет убита.
Ну, невозможно присвоить Ttext
на 0x400082
, не нарушив .text
ограничение выравнивания раздела (которое равно 4).Вы должны сохранять .text адрес выровненным по крайней мере на 4-байтовой границе (или изменить требуемое выравнивание на .text
).
Когда я устанавливаю начальный адрес 0x400078, 0x40007c, 0x400080, 0x400084, ..., 0x400098 и использовать GNU-ld 2.20.1, программа работает.
Однако, когда я использую текущий снимок CVS binutils, программа работает для 0x400078, 0x40007c, 0x400088, 0x40008c и получает Killed для 0x4000800x400084, 0x400090, 0x400094, 0x400098.Это может быть ошибка в компоновщике, или я нарушаю какое-то другое ограничение (хотя я не вижу, какое именно).
На данный момент, если вы действительно заинтересованы, я предлагаюзагрузка исходных файлов binutils, сборка ld
и выяснение того, что именно заставляет его создавать два PT_LOAD
сегмента вместо одного.
Обновление 2:
Форсировать новый сегмент для секцийс перекрывающимися LMA.
Ах!Это просто означает, что вам нужно убрать .data
с дороги.Это делает рабочий исполняемый файл:
ld -N -o t t.o -e0x400080 -Ttext=0x400080 -Tdata=0x400180