Удаление символов из объектного файла в windows

Есть ли способ удалить (или сделать локальными) символы в объектном файле? Ищу что-то вроде objcopy --keep-global-symbol на linux.

Или, может быть, есть способ указать компоновщику, какие символы нужно скрыть? Я нашел эту страницу: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx, который описывает файлы .Def, и мое впечатление от чтения таково, что я могу использовать эти файлы не только для dll, но и для статических библиотек. Это правда?

Мне это нужно, потому что я связываюсь с двумя библиотеками A и B, которые экспортируют одни и те же символы. A связан динамически, а B связан статически. Если символы экспортируются как A, так и B, я хочу, чтобы мое приложение использовало символ из A, плюс я хочу использовать некоторые символы из B (которые есть только в B).


person Igor    schedule 11.10.2018    source источник


Ответы (1)


Если вы установите один из портов Mingw GCC, например mingw-w64, тогда вы также получите порты binutils для двоичных файлов Windows PE и уметь пользоваться знакомым objcopy --keep-global-symbol.

Найдите его в каталоге bin выбранной вами установки, например C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev0\mingw64\bin

Однако ...

Здесь у вас вполне может быть проблема XY, потому что компоновщик разрешит символ из первой библиотеки во входной последовательности, которая определяет его, и игнорирует определения в более поздних библиотеках; поэтому вы можете отдать предпочтение определениям из DLL, просто связав их перед статической библиотекой. Иллюстрация:

foo_static.c

#include <stdio.h>

void foo(void)
{
    puts("foo_static");
}

bar_static.c

#include <stdio.h>

void bar(void)
{
    puts("bar_static");
}

foo_dynamic.c

#include <stdio.h>

__declspec(dllexport) void foo(void)
{
    puts("foo_dynamic");
}

gum_dynamic.c

#include <stdio.h>

__declspec(dllexport) void gum(void)
{
    puts("gum_dynamic");
}

Скомпилируйте *_static.c исходные файлы и заархивируйте объектные файлы в статической библиотеке static.lib:

>cl -c *_static.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

bar_static.c
foo_static.c
Generating Code...

>lib -out:static.lib *_static.obj
Microsoft (R) Library Manager Version 14.11.25547.0
Copyright (C) Microsoft Corporation.  All rights reserved.

Скомпилируйте *_dynamic.c исходные файлы и свяжите объектные файлы в DLL dynamic.dll:

>cl -c *_dynamic.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

foo_dynamic.c
gum_dynamic.c
Generating Code...

>link -dll -out:dynamic.dll *_dynamic.obj
Microsoft (R) Incremental Linker Version 14.11.25547.0
Copyright (C) Microsoft Corporation.  All rights reserved.

   Creating library dynamic.lib and object dynamic.exp

Обратите внимание, что функция foo определена (по-разному) в static.lib и dynamic.dll. bar определяется только в static.lib. gum определяется только в dynamic.dll

Вот исходный код программы, который вызывает foo, bar и gum:

main.c

extern void foo();
extern void bar();
extern void gum();

int main()
{
    foo();
    bar();
    gum();
    return 0;
}

который мы компилируем:

>cl -c main.c
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25547 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

main.c

Затем мы связываем программу prog вот так:

>link -out:prog.exe main.obj static.lib dynamic.lib
Microsoft (R) Incremental Linker Version 14.11.25547.0
Copyright (C) Microsoft Corporation.  All rights reserved.

с static.lib первым. Программа выводит:

>prog.exe
foo_static
bar_static
gum_dynamic

Итак, foo было решено из static.lib, а определение из dynamic.dll было проигнорировано.

Теперь давайте повторно установим связь с обратным порядком библиотек и снова запустим prog:

>link -out:prog.exe main.obj dynamic.lib static.lib
Microsoft (R) Incremental Linker Version 14.11.25547.0
Copyright (C) Microsoft Corporation.  All rights reserved.


>prog.exe
foo_dynamic
bar_static
gum_dynamic

На этот раз foo было решено из dynamic.dll, а определение из static.lib было проигнорировано.

person Mike Kinghan    schedule 15.10.2018
comment
Спасибо, я попробую, но в идеале я бы предпочел не устанавливать никаких дополнительных программ. Вы случайно не знаете ответ на вопрос, который я только что добавил при редактировании (о файлах .Def)? - person Igor; 15.10.2018
comment
@Igor Нет, .def файл может быть использован компоновщиком только при компоновке программы или DLL. Не статическая библиотека, потому что статическая библиотека, в отличие от программы или DLL, создается не компоновщиком (link), а только архиватором (lib). См. статические библиотеки. Однако мой расширенный ответ может помочь. - person Mike Kinghan; 16.10.2018
comment
Спасибо за объяснение, это действительно решает мою проблему. Правильно ли я понимаю (из опубликованной вами ссылки), что это поведение зависит от компоновщика? Дало бы ли это те же результаты на Linux (с использованием GNUs ld)? - person Igor; 16.10.2018
comment
@Igor Да, это поведение будет таким же с набором инструментов GNU / Linux - person Mike Kinghan; 17.10.2018