Ответ 1
почему я не могу заставить 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
к линии ссылок.
Update:
Однако, когда я пытаюсь установить связь с программой 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 для 0x400080, 0x400084, 0x400090, 0x400094, 0x400098. Это может быть ошибкой в компоновщике, или я нарушаю какое-то другое ограничение (я не вижу, хотя).
В этот момент, если вы действительно заинтересованы, я предлагаю загрузить источники binutils, построив ld
, и выясню, что именно заставляет его создавать два сегмента PT_LOAD
вместо одного.
Обновление 2:
Настроить новый сегмент для разделов с перекрывающимися LMA.
Ах! Это просто означает, что вам нужно переместить .data
в сторону. Это делает рабочий исполняемый файл:
ld -N -o t t.o -e0x400080 -Ttext=0x400080 -Tdata=0x400180