Можно ли отменить привязку объектных файлов к исполняемому файлу?

Предыстория: я рассматриваю возможность разработки менеджера пакетов, похожего на portage в Gentoo Linux (может закончиться тем, что я разветвлю portage). Для тех, кто мало что знает о Gentoo, это дистрибутив на основе исходного кода, что означает, что все пакеты скомпилированы из исходного кода. В настоящее время можно скомпилировать программу в объектные файлы, а затем в исполняемые файлы.

$ gcc -c  a.c -o a.o
$ gcc -c  b.c -o b.o
$ gcc a.o b.o -o executable

Улучшения, которые я хотел бы внести в portage, заключаются в следующем.

  1. Возможность перекомпилировать только обновленные объектные файлы (отслеживать изменения с помощью GIT или иным образом).
  2. Декомпилировать/развязать исполняемый файл с объектными файлами.
  3. Перекомпилируйте/повторно свяжите объектные файлы, заменив только старые объектные файлы обновленными объектными файлами (изменения отслеживаются с помощью GIT или иным образом).
  4. Затем вновь скомпилированный пакет заменяет старый пакет. (тривиальная задача)

Обоснование: я пользователь Arch Linux, которому нравится идея дистрибутива на основе исходного кода, но меня не беспокоит огромная задача поддержания моей системы в актуальном состоянии. Я также выполняю большую часть своей работы на портативном компьютере с небольшим жестким диском, отсюда и причина декомпиляции/отключения связи исполняемого файла с объектными файлами, а не просто сохранение объектных файлов, которые занимают много места. Это также, вероятно, уменьшит общее время компиляции системы, поскольку потребность в повторной компиляции большей части исходного кода будет значительно уменьшена. Это также позволило бы легко изменить USE-флаги пакета без необходимости полной перекомпиляции.

Вопрос: можно ли скомпилировать объектные файлы в исполняемый файл, а затем декомпилировать обратно в объектные файлы. Пример этого ниже.

$ gcc -c  a.c -o a.o
$ gcc -c  b.c -o b.o
$ gcc a.o b.o -o executable

а потом

$ SomeCommand executable 
output << a.o b.o

Если это сейчас невозможно. Можно ли изменить версию компоновщика GNU «$ld», чтобы регистрировать изменения, которые он вносит при связывании объектных файлов, чтобы намеренно сделать программу «обратно спроектированной» ???

Редактировать. Другим вариантом использования этого может быть слишком большое отделение отдельного объектного файла от исполняемого файла большого проекта, чтобы заменить отделенный объектный файл новым и повторно связать его. Это уменьшит накладные расходы на повторное связывание больших проектов из множества разных файлов, когда обновляется только один. Это позволило бы выполнять инкрементную компиляцию на двоичном уровне.


person silvergasp    schedule 03.09.2015    source источник
comment
Хм, возможно, вы можете создать собственный скрипт компоновщика, который сохраняет имена файлов .o и связывает их с разделами .text, .data и т. д. Позже вы можете извлечь и заменить их на elfsh (eresi-project.org/wiki/TheELFsh). Как именно это могло бы работать, я не в силах, хотя ^_^   -  person Johannes Schaub - litb    schedule 03.09.2015
comment
Как вы собираетесь восстанавливать небольшие исполняемые файлы .obj, которые (как вы сами сказали) довольно велики? Я не думаю, что компоновщик сжимает исполняемый файл из-за какого-либо сжатия — он просто отбрасывает ненужную информацию. Таким образом, если бы вы встроили в него элементы, необходимые для реверсирования процесса, размер исполняемого файла увеличился бы на столько же, что сделало бы весь процесс бесполезным.   -  person rr-    schedule 03.09.2015
comment
Обычно вы теряете информацию при ссылке. Во-первых, вы объединяете разделы каждого объектного файла в один и тот же раздел, превращая его в просто большой двоичный объект. Если бы вы этого не сделали, я полагаю, что можно было бы снова разобрать исполняемый файл (если вы знаете, какие разделы принадлежат какому объектному файлу).   -  person skyking    schedule 03.09.2015
comment
Не забывайте про файлы .a :p   -  person Johannes Schaub - litb    schedule 03.09.2015


Ответы (2)


Нет, это невозможно. Большая часть работы компоновщика заключается в замене символических ссылок (действительных для любой комбинации объектных файлов, связываемых вместе) числовыми смещениями (действительными только для определенного способа, которым компоновщик решил разместить эту конкретную комбинацию объектных файлов в это конкретное время). . После того, как ссылки «запечены» таким образом, их невозможно восстановить.

person Sneftel    schedule 03.09.2015
comment
GNU ld имеет параметр --emit-relocs, который может заставить его работать. Затем он может попытаться отменить перемещения. Однако не уверен, что это работает для всех перемещений. - person Johannes Schaub - litb; 03.09.2015
comment
@JohannesSchaub-litb Хороший вопрос, но с оставленными разделами перемещения единственная разумная мотивация для этого (уменьшение размера на диске) практически исчезнет. - person Sneftel; 03.09.2015
comment
Но что, если бы эти данные хранились отдельно в отдельном файле (то есть в файле, в котором хранились бы числовые смещения, заменяющие символические ссылки). В основном то, что я ищу, - это способ заставить компоновщик регистрировать то, что он делает, и в этом случае изменения можно просто отменить??? или я что-то пропустил?? - person silvergasp; 03.09.2015
comment
Нет, вы, конечно, могли бы написать компоновщик таким образом. Но результат не будет иметь существенного преимущества по сравнению с сохранением объектных файлов. Конечно, использование диска будет сопоставимо. - person Sneftel; 03.09.2015
comment
@Sneftel Ваш комментарий ответил на мой вопрос, если вы были бы рады включить это в свой ответ, я приму его ... Не уверен, почему за меня проголосовали против, но мне показалось разумным задать вопрос: P Спасибо за ваше время - person silvergasp; 03.09.2015

Это может быть выполнимо, если вы измените/настроите ld, чтобы разделить разделы для каждого объектного файла, а также сохранить таблицу перемещения для каждого объектного файла в исполняемом файле. Также вы должны убедиться, что ld сохраняет имена объектных файлов в исполняемом файле, если вы хотите получить исходные имена файлов.

По сути, компоновщик может просто соединить объектные файлы вместе, а затем выполнить перемещения, если перемещения обратимы, вы сможете обратить процесс вспять.

person skyking    schedule 03.09.2015