Вот такая вот задача.
Есть некий код на C, фактически — один файл .C в котором определенны несколько функций, структур и т.п.
Задача собственно в том, что-бы оттранслировать этот код в машинный и получить на выходе raw-машинный код(а не объектный .obj или .o), в котором все эти функции и лежат — что-то типа прошивки получается. Естественно нужно что-бы как результат была выдана таблица точек входа. Ищу компилятор который это может более менее штатными средствами. Целевая архитектура x86/x64_86.
Здравствуйте, PanychY, Вы писали:
PY>Приветствую
PY>Вот такая вот задача. PY>Есть некий код на C, фактически — один файл .C в котором определенны несколько функций, структур и т.п. PY>Задача собственно в том, что-бы оттранслировать этот код в машинный и получить на выходе raw-машинный код(а не объектный .obj или .o), в котором все эти функции и лежат — что-то типа прошивки получается.
ну а в объектном файле что лежит, по-твоему, если не raw-машинный код? открой его дизассемблером и все будет
А если компилируешь с -fPIC (position-independent code), то в коде не будет привязок по конкретным адресам и его можно будет загружать по любом адресу и запускать без изменений.
На линуксе objdump тебе поможет, там и адреса прописаны для каждой функции будут.
Здравствуйте, jazzer, Вы писали:
J>Здравствуйте, PanychY, Вы писали:
J> ну а в объектном файле что лежит, по-твоему, если не raw-машинный код? открой его дизассемблером и все будет
ни разу не raw. да еще в перемешку со структурами самого объектного файла. зачем открывать дизассемблером? тогда уже компилятор просить сгенерить асм-листинг. как минимум мы устраняем дизассемблер.
J>А если компилируешь с -fPIC (position-independent code),
не все компиляторы поддерживают такую фичу.
J> то в коде не будет привязок по конкретным адресам J> и его можно будет загружать по любом адресу и запускать без изменений.
сказки. чем вам поможет -fPIC? там все равно сырого кода не будет. ну то есть будет, конечно, но не одиним куском. как .com файл его не загрузишь. исключение составляет вырожденный случай, когда нет глобальных/статических переменных и нет ссылок на внешние (по отношению к данному файлу) функции. но в этом случае и ms vc без всякий ключей сгенериует такой же позиционно-независимый код, ибо вызовы функций данного модуля и условные переходы в x86 относительны. базовые библиотечные вызовы ms vc лихо внедряет в код по месту вызова. но это не дает гарантий, что при создании локального массива компилятор не дернет RTL функцию для аллокации стековой памяти.
J>На линуксе objdump тебе поможет, там и адреса прописаны для каждой функции будут.
здравый смысл подсказывает юзать objcopy или man ld. а дальше --oformat=binary. как-то так...
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Здравствуйте, PanychY, Вы писали:
PY>Приветствую
PY>Задача собственно в том, что-бы оттранслировать этот код в машинный и получить на выходе raw-машинный код PY>(а не объектный .obj или .o), в котором все эти функции и лежат — что-то типа прошивки получается.
под никсами: ld yourfile.o -o yourfile.bin --oformat=binary, но это не для всех файлов. даже если компилировать с ключом -fPIC, то все равно может не слинковаться в raw, если, например, у вас глобальные переменные там.
> Естественно нужно что-бы как результат была выдана таблица точек входа.
??? каких точек входа? format=binary ищет _start. если не находит, то ругается матом.
> Ищу компилятор который это может более менее штатными средствами. Целевая архитектура x86/x64_86.
гнусь делает штатными средствами, но не для всех .с файлов. ключ -fPIC он все же не для бинарных файлов и потому тут не поможет.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Здравствуйте, мыщъх, Вы писали:
J>> ну а в объектном файле что лежит, по-твоему, если не raw-машинный код? открой его дизассемблером и все будет М>ни разу не raw. да еще в перемешку со структурами самого объектного файла. зачем открывать дизассемблером?
чтоб посмотреть, что компилятор нагенерил, вестимо
J>>А если компилируешь с -fPIC (position-independent code), М>не все компиляторы поддерживают такую фичу.
ну я с gcc работаю, про него и говорю.
У других что-то похожее должно быть тоже, иначе как DLL-ки выпекать?
J>> то в коде не будет привязок по конкретным адресам J>> и его можно будет загружать по любом адресу и запускать без изменений. М>сказки. чем вам поможет -fPIC? там все равно сырого кода не будет. ну то есть будет, конечно, но не одиним куском. как .com файл его не загрузишь. исключение составляет вырожденный случай, когда нет глобальных/статических переменных и нет ссылок на внешние (по отношению к данному файлу) функции.
У меня такое подозрение, что ТС как раз такой вырожденный случай и нужен. Иначе проще и прямее либу собрать и линковать по-честному.
М>но в этом случае и ms vc без всякий ключей сгенериует такой же позиционно-независимый код, ибо вызовы функций данного модуля и условные переходы в x86 относительны. базовые библиотечные вызовы ms vc лихо внедряет в код по месту вызова.
хз, про мс ничего не могу сказать, не пользуюсь.
М>но это не дает гарантий, что при создании локального массива компилятор не дернет RTL функцию для аллокации стековой памяти.
Поэтому я и говорил про дизассемблер — надо всегда проверять, что там компилятор нагенерил
Просто без внятной формулировки задачи не очень понятно, что именно нужно ТС.
Как вариант — он просто генерит функции типа "умножить на 2" и потом собрается дергать их, типа плагины для бедных.
Но, имхо, все это гораздо прямее длл-ками делается.
J>>На линуксе objdump тебе поможет, там и адреса прописаны для каждой функции будут. М>здравый смысл подсказывает юзать objcopy или man ld. а дальше --oformat=binary. как-то так...
ну так все равно их надо на объектный файл натравливать, от объектника не уйти никуда по-любому, а ТС-то хотел, чтоб объектников не было.
Здравствуйте, jazzer, Вы писали:
J>>> ну а в объектном файле что лежит, по-твоему, если не raw-машинный код? открой его дизассемблером и все будет М>>ни разу не raw. да еще в перемешку со структурами самого объектного файла. зачем открывать дизассемблером? J>чтоб посмотреть, что компилятор нагенерил, вестимо
J>>>А если компилируешь с -fPIC (position-independent code), М>>не все компиляторы поддерживают такую фичу. J>ну я с gcc работаю, про него и говорю. J>У других что-то похожее должно быть тоже, иначе как DLL-ки выпекать?
DLL-ки обычно при загрузке патчатся. Для чего в них, как правило, имеется секция .reloc
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Тот кто сидит в пруду, Вы писали:
ТКС>DLL-ки обычно при загрузке патчатся. Для чего в них, как правило, имеется секция .reloc
Только не секция, а директория. Секция это просто контейнер, внутри может быть что угодно.
On 04/17/2012 10:00 AM, jazzer wrote:
> М>не все компиляторы поддерживают такую фичу. > ну я с gcc работаю, про него и говорю. > У других что-то похожее должно быть тоже, иначе как DLL-ки выпекать?
DLL-и загружаются в память, и в них есть таблица смещений адресов, которые
тьюнются по месту загрузки.
А то, что ты имееш в виду, называлось когда-то .com-файл, но сейчас
естественно современные виндовые компиляторы "его не умеют"
Здравствуйте, Тот кто сидит в пруду, Вы писали:
ТКС>DLL-ки обычно при загрузке патчатся. Для чего в них, как правило, имеется секция .reloc
эта секция и в обычных объектниках есть.
Просто PIC, вроде как, патчить не нужно, этим он и отличается от relocatable, который нужно патчить (просто лишний уровень косвенности вводится).
Здравствуйте, jazzer, Вы писали:
ТКС>>DLL-ки обычно при загрузке патчатся. Для чего в них, как правило, имеется секция .reloc
J>эта секция и в обычных объектниках есть.
Ну да, только линкер ее потом в готовый экзешник не вставляет, за ненадобностью. А вот для собственно сборки exe из нескольких объектников фиксапы линкеру тоже нужны.
J>Просто PIC, вроде как, патчить не нужно, этим он и отличается от relocatable, который нужно патчить (просто лишний уровень косвенности вводится).
Понятно, что PIC патчить не нужно. Просто утверждение "У других что-то похожее должно быть тоже, иначе как DLL-ки выпекать?" вообще отрицает фиксапы. А в MSVC принято пользоваться именно ими. Хотя ключ для PIC вроде когда-то был, но вот прямо сейчас я его в хелпе что-то не нашел. Так что наверное нету больше. А может это я с чем другим путаю, и не было его у МС никогда.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, jazzer, Вы писали:
J>... J>>>А если компилируешь с -fPIC (position-independent code), М>>не все компиляторы поддерживают такую фичу. J>ну я с gcc работаю, про него и говорю. J>У других что-то похожее должно быть тоже, иначе как DLL-ки выпекать?
Здравствуйте, Тот кто сидит в пруду, Вы писали:
J>>>>А если компилируешь с -fPIC (position-independent code), М>>>не все компиляторы поддерживают такую фичу. J>>ну я с gcc работаю, про него и говорю. J>>У других что-то похожее должно быть тоже, иначе как DLL-ки выпекать? ТКС>DLL-ки обычно при загрузке патчатся. Для чего в них, как правило, имеется секция .reloc
Господа, я жутко извиняюсь, но вы что с дуба рухнули? Какой не PIC код под x86?!
Он там весь PIC бай дизайн. Обращение к данным, то же бай дизайн по фиксированному адресу. Для них релоки и сущетвуют. Собственно кто мешает собрать всё в одну секцию и сделать авторелок? У gcc кстати какя-то такая фигня была. Вместо секции перемещений, гнутый binutils может генерировать код автонастройки смещнеий для доступа к секциям данных.
Здравствуйте, Alexéy Sudachén, Вы писали:
AS>Господа, я жутко извиняюсь, но вы что с дуба рухнули? Какой не PIC код под x86?!
Однозначно. Вместе с разработчиками gcc
AS>Он там весь PIC бай дизайн. Обращение к данным, то же бай дизайн по фиксированному адресу.
Эти два предложения друг другу противоречат, не находите?
AS>Для них релоки и сущетвуют. Собственно кто мешает собрать всё в одну секцию и сделать авторелок? У gcc кстати какя-то такая фигня была. Вместо секции перемещений, гнутый binutils может генерировать код автонастройки смещнеий для доступа к секциям данных.
Ну мало ли по каким причинам хочется PIC. Может мы его собираемся в ПЗУ зашивать, а адрес ПЗУ задавать перемычками.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Тот кто сидит в пруду, Вы писали:
AS>>Господа, я жутко извиняюсь, но вы что с дуба рухнули? Какой не PIC код под x86?! ТКС>Однозначно. Вместе с разработчиками gcc
Вы PIC и PIE не путаете?
AS>>Он там весь PIC бай дизайн. Обращение к данным, то же бай дизайн по фиксированному адресу. ТКС>Эти два предложения друг другу противоречат, не находите?
Не в x86 весь код базонезависим и другого не бывает, если мне склероз конечно не изменяет.
Обращение к данным можно только относительно базы. Откуда берётся база данных это уже вопрос структуры исполняемого модуля, от места загрузки кода это вообще никак не зависит.
AS>>Для них релоки и сущетвуют. Собственно кто мешает собрать всё в одну секцию и сделать авторелок? У gcc кстати какя-то такая фигня была. Вместо секции перемещений, гнутый binutils может генерировать код автонастройки смещнеий для доступа к секциям данных. ТКС>Ну мало ли по каким причинам хочется PIC. Может мы его собираемся в ПЗУ зашивать, а адрес ПЗУ задавать перемычками.
Дык, можно элементарно писать на С PIC код, без какой либо специальной поддержки со стороны компилятора. Я же это делаю.
Здравствуйте, Alexéy Sudachén, Вы писали:
AS>>>Господа, я жутко извиняюсь, но вы что с дуба рухнули? Какой не PIC код под x86?! ТКС>>Однозначно. Вместе с разработчиками gcc
AS>Вы PIC и PIE не путаете?
Если и путаю, то только вместе с разработчиками gcc, назвавшими опцию -fPIC.
А вот что вы имеете в виду под PIE, я не в курсе.
AS>>>Он там весь PIC бай дизайн. Обращение к данным, то же бай дизайн по фиксированному адресу. ТКС>>Эти два предложения друг другу противоречат, не находите?
AS>Не в x86 весь код базонезависим и другого не бывает, если мне склероз конечно не изменяет.
Вот прямо сейчас скопировал из дизассемблера — call 022EC860. Вполне себе привязано к конкретному адресу. А на самом деле это вызов boost::filesystem3::filesystem_error::filesystem_error
Но, собственно, я имел в виду, что "бай дизайн по фиксированному адресу" и "базонезависим" — это взаимопротиворечащие понятия. Базонезависим — это когда мы можем поместить код по любому адресу, передать на него управление, и он отработает одинаково. Без всяких дополнительных телодвижений, типа коррекции адресов внешними средствами или самомодификации (которая может быть в конкретном окружении невозможна).
AS>Обращение к данным можно только относительно базы. Откуда берётся база данных это уже вопрос структуры исполняемого модуля, от места загрузки кода это вообще никак не зависит.
Процессор ничего про структуру исполняемого модуля не знает, что по адресу IP/EIP/RIP найдет, то и выполняет. И вообще может не быть никакого модуля и загрузки.
AS>>>Для них релоки и сущетвуют. Собственно кто мешает собрать всё в одну секцию и сделать авторелок? У gcc кстати какя-то такая фигня была. Вместо секции перемещений, гнутый binutils может генерировать код автонастройки смещнеий для доступа к секциям данных. ТКС>>Ну мало ли по каким причинам хочется PIC. Может мы его собираемся в ПЗУ зашивать, а адрес ПЗУ задавать перемычками.
AS>Дык, можно элементарно писать на С PIC код, без какой либо специальной поддержки со стороны компилятора.
Можно. Можно и без типизации писать. Или на ассемблере. Только вероятность ошибок на порядки повышается.
AS>Я же это делаю.
Учитывая, что вы здесь наговорили — сильно в этом сомневаюсь. Как минимум, мы под PIC понимаем разные вещи.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
AS>>Не в x86 весь код базонезависим и другого не бывает, если мне склероз конечно не изменяет. ТКС>Вот прямо сейчас скопировал из дизассемблера — call 022EC860. Вполне себе привязано к конкретному адресу. А на самом деле это вызов
Это вызов по смещению от инструкции, а вот call [022EC860] вызов по адресу в памяти. Использование второго обусловленно спецификой формата PE, где линковка с другими модулями происходит через таблицу адресов. Прямого вызова по адресу кроме вызова шлюза/таски/сегмента (дескриптор + смещение), я чего-то не припоминаю. Ни один компилятор С/C++ такие вызова в плоской модели не генерирует.
ТКС>Но, собственно, я имел в виду, что "бай дизайн по фиксированному адресу" и "базонезависим" — это взаимопротиворечащие понятия. Базонезависим — это когда мы можем поместить код по любому адресу, передать на него управление, и он отработает одинаково. Без всяких дополнительных телодвижений, типа коррекции адресов внешними средствами или самомодификации (которая может быть в конкретном окружении невозможна).
Назови мне процессор в котором дуступ к памяти можно делать по смещению от инструкции? Так на всякий случай.
Давай проведём эксперемент. Выделяем кусок исполняемой памяти равный по размеру секции кода, копируем туда секцию кода и передаём управление на соответствующий адрес в новом месте. Работать будет? Можно даже для верности затереть старую секцию.
Ещё раз повторю, код в x86 всегда базонезависим. Вопрос в том как код работает с данными. Если имеется в виду генерация таблицы для глобальных переменных и резолв табдлицы через фейковый call, то в винде, если мне склероз не изменят, gcc это не делает. В принципе. Так что своими ручками. Но от того делает это gcc или нет, x86 код не перестаёт быть независимым от размещения.
AS>>Я же это делаю. ТКС>Учитывая, что вы здесь наговорили — сильно в этом сомневаюсь. Как минимум, мы под PIC понимаем разные вещи.
Здравствуйте, Alexéy Sudachén, Вы писали:
AS>>>Не в x86 весь код базонезависим и другого не бывает, если мне склероз конечно не изменяет. ТКС>>Вот прямо сейчас скопировал из дизассемблера — call 022EC860. Вполне себе привязано к конкретному адресу. А на самом деле это вызов
AS>Это вызов по смещению от инструкции, а вот call [022EC860] вызов по адресу в памяти. Использование второго обусловленно спецификой формата PE, где линковка с другими модулями происходит через таблицу адресов. Прямого вызова по адресу кроме вызова шлюза/таски/сегмента (дескриптор + смещение), я чего-то не припоминаю. Ни один компилятор С/C++ такие вызова в плоской модели не генерирует.
Ну ты вообще-то утверждал, что "в x86 весь код базонезависим и другого не бывает", я тебе просто привел контрпример. А уж чем существование такого кода обусловлено — дело десятое.
ТКС>>Но, собственно, я имел в виду, что "бай дизайн по фиксированному адресу" и "базонезависим" — это взаимопротиворечащие понятия. Базонезависим — это когда мы можем поместить код по любому адресу, передать на него управление, и он отработает одинаково. Без всяких дополнительных телодвижений, типа коррекции адресов внешними средствами или самомодификации (которая может быть в конкретном окружении невозможна).
AS>Назови мне процессор в котором дуступ к памяти можно делать по смещению от инструкции? Так на всякий случай.
Так, уже стало "по смещению от инструкции", вместо "по фиксированному адресу" Прогресс однако
AS>Давай проведём эксперемент. Выделяем кусок исполняемой памяти равный по размеру секции кода, копируем туда секцию кода и передаём управление на соответствующий адрес в новом месте. Работать будет? Можно даже для верности затереть старую секцию.
Я легко могу изготовить такой кусок кода, который при таком эксперименте перестанет работать.
AS>Ещё раз повторю, код в x86 всегда базонезависим.
Ещё раз повторю, применение слова "всегда" здесь неуместно, раз имеются контрпримеры. Правильно говорить "генерация базонезависимого кода для x86 не представляет трудности".
AS>Вопрос в том как код работает с данными. Если имеется в виду генерация таблицы для глобальных переменных и резолв табдлицы через фейковый call, то в винде, если мне склероз не изменят, gcc это не делает. В принципе. Так что своими ручками. Но от того делает это gcc или нет, x86 код не перестаёт быть независимым от размещения.
Внутренне противоречивое утверждение.
Одним из 33 полных кавалеров ордена "За заслуги перед Отечеством" является Геннадий Хазанов.
Здравствуйте, Alexéy Sudachén, Вы писали:
AS>Назови мне процессор в котором дуступ к памяти можно делать по смещению от инструкции? Так на всякий случай.
Some processor architectures, like the Motorola 68000, Motorola 6809, Knuth's MMIX, ARM and x86-64 allow referencing data by offset from the program counter. This is specifically targeted at making position-independent code smaller, less register demanding and hence more efficient.
Интерес представляют конечно же не учебный MMIX, а ARM и x86-64. Да, в x86-64 можно наконец-то писать нормальный PIC, где глобальные переменные адресуются через смещение относительно значения регистра RIP.
Здравствуйте, MasterZiv, Вы писали:
MZ>On 04/17/2012 10:00 AM, jazzer wrote:
MZ>А то, что ты имееш в виду, называлось когда-то .com-файл, но сейчас MZ>естественно современные виндовые компиляторы "его не умеют"
не компиляторы, а линкеры. gcc умеет.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.