I don't think this is a pure C programming question, but it's related.
I don't think this is a pure C programming question, but it's related.
I'm building a static library mylib.a with all the object files except main.o, and the final executable linking together main.o and mylib.a.
I want to remove from the final exe everything present in mylib.a that
is not used in main.o.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are defined
in mod1.c. main() is the only function in main.c and only foo1() is
called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in WSL doesn't.
Why?
pozz <pozzugno@gmail.com> wrote:
I don't think this is a pure C programming question, but it's related.
I'm building a static library mylib.a with all the object files except
main.o, and the final executable linking together main.o and mylib.a.
I want to remove from the final exe everything present in mylib.a that
is not used in main.o.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are defined
in mod1.c. main() is the only function in main.c and only foo1() is
called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a
objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in WSL
doesn't.
Why?
Support for '-ffunction-sections' and '-fdata-sections' is target
platform dependent (and version dependent). Also there may be
platform specific quirks. If your toolchain does not properly
support them, then you need to use old method, that is define each
function in a separate file.
I don't think this is a pure C programming question, but it's related.
I'm building a static library mylib.a with all the object files except main.o, and the final executable linking together main.o and mylib.a.
I want to remove from the final exe everything present in mylib.a that
is not used in main.o.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are defined
in mod1.c. main() is the only function in main.c and only foo1() is
called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in WSL doesn't.
Why?
I don't think this is a pure C programming question, but it's related.
I'm building a static library mylib.a with all the object files
except main.o, and the final executable linking together main.o and
mylib.a.
I want to remove from the final exe everything present in mylib.a
that is not used in main.o.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are
defined in mod1.c. main() is the only function in main.c and only
foo1() is called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in
WSL doesn't.
Why?
On 28/08/2025 18:12, pozz wrote:
I don't think this is a pure C programming question, but it's related.
I'm building a static library mylib.a with all the object files except
main.o, and the final executable linking together main.o and mylib.a.
My first question is "Why?" Why not simply link all the object files together?
I want to remove from the final exe everything present in mylib.a that
is not used in main.o.
My second question is "Why?" When you are working on embedded targets, saving space like this in the executable is often a very good idea. On
a PC, it is rarely worth the effort.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are
defined in mod1.c. main() is the only function in main.c and only
foo1() is called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a
objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in
WSL doesn't.
Why?
Why are you using "-ffunction-sections" and "-fdata-sections" ?
They
can be helpful in some ways for omitting code and data that is defined
in the code, but not actually used in the executable. But they can also make linking slower, and "-fdata-sections" can reduce optimisations (especially if you have "-fcommon", which was the default in older gcc).
Il 29/08/2025 11:05, David Brown ha scritto:
On 28/08/2025 18:12, pozz wrote:
I don't think this is a pure C programming question, but it's related.
I'm building a static library mylib.a with all the object files
except main.o, and the final executable linking together main.o and
mylib.a.
My first question is "Why?" Why not simply link all the object files
together?
Because I want to start creating tests on my projects and one simple approach is what I have described. All is in a static library (a
collection of object files), except main.o where is only main().
If I want to create test1.c (with its main), I have to only link test1.o with library.
I want to remove from the final exe everything present in mylib.a
that is not used in main.o.
My second question is "Why?" When you are working on embedded
targets, saving space like this in the executable is often a very good
idea. On a PC, it is rarely worth the effort.
This question was born because I found another problem.
I have a library distributed in source codes. One function in one source code needs to access a global array that *must* be defined somewhere in
the project.
As I wrote, I'm creating some tests. Not all the tests use that
function, so I thought it would be safe to not have the definition of
the global array, but this isn't true in my project and building system.
The linker complains because it doesn't find the global array.
I expected the unused function, with its references, would have been
removed by the linker.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are
defined in mod1.c. main() is the only function in main.c and only
foo1() is called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a
objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in
WSL doesn't.
Why?
Why are you using "-ffunction-sections" and "-fdata-sections" ?
Because each function is in its section and can be removed if unused by
the garbage collector of the linker (at least, so I understood).
They can be helpful in some ways for omitting code and data that is
defined in the code, but not actually used in the executable. But
they can also make linking slower, and "-fdata-sections" can reduce
optimisations (especially if you have "-fcommon", which was the
default in older gcc).
I don't think this is a pure C programming question, but it's related.
I'm building a static library mylib.a with all the object files except main.o, and the final executable linking together main.o and mylib.a.
I want to remove from the final exe everything present in mylib.a that
is not used in main.o.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are defined
in mod1.c. main() is the only function in main.c and only foo1() is
called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in WSL doesn't.
Why?
On 29/08/2025 12:39, pozz wrote:
Il 29/08/2025 11:05, David Brown ha scritto:
On 28/08/2025 18:12, pozz wrote:
I don't think this is a pure C programming question, but it's related. >>>>
I'm building a static library mylib.a with all the object files
except main.o, and the final executable linking together main.o and
mylib.a.
My first question is "Why?" Why not simply link all the object files
together?
Because I want to start creating tests on my projects and one simple
approach is what I have described. All is in a static library (a
collection of object files), except main.o where is only main().
If I want to create test1.c (with its main), I have to only link
test1.o with library.
The only "benefit" you get from using a library in this situation is
that you might conceivably save a couple of lines in your makefile,
and
if you are using spinning rust drives and a PC from the 1990's, you
might save a second or two from the build. It is not worth the bother.
I want to remove from the final exe everything present in mylib.a
that is not used in main.o.
My second question is "Why?" When you are working on embedded
targets, saving space like this in the executable is often a very
good idea. On a PC, it is rarely worth the effort.
This question was born because I found another problem.
I have a library distributed in source codes. One function in one
source code needs to access a global array that *must* be defined
somewhere in the project.
Okay.
As I wrote, I'm creating some tests. Not all the tests use that
function, so I thought it would be safe to not have the definition of
the global array, but this isn't true in my project and building
system. The linker complains because it doesn't find the global array.
I expected the unused function, with its references, would have been
removed by the linker.
The "--gc-sections" gnu linker option works for elf files, but is "experimental" for coff/pe. Maybe it simply doesn't work as effectively for mingw, which will be generating Windows-style coff/pe binaries,
while it works for WSL which uses Linux-style elf binaries.
But while I appreciate that you expected linker garbage collection to
work here, you still haven't answered why you feel it is important. (If you are just trying to understand why it doesn't work, that's fine by me.)
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are
defined in mod1.c. main() is the only function in main.c and only
foo1() is called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a >>>> objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in
WSL doesn't.
Why?
Why are you using "-ffunction-sections" and "-fdata-sections" ?
Because each function is in its section and can be removed if unused
by the garbage collector of the linker (at least, so I understood).
They are potentially useful if you have a significant amount of extra
code and/or data that is in your source code and not wanted in the final binary, /and/ that it is important for the binary to be as small as reasonably possible.
As I understand it, you have an embedded program with lots of source
code, and you want to test different parts of it by compiling with
different small "main" functions on a PC. I am not sure if you said the main program was for an embedded system, or if I am assuming that
because you are one of the few people keeping comp.arch.embedded alive
by starting new threads there :-)
For the main program, function and data sections are probably not needed because you the source code that you build for the project is needed for
the program - if there was a lot that you didn't need, it wouldn't be in
the project build.
For the test programs, function and data sections are not needed because
the size of the test binaries on the PC is irrelevant.
Again - if your questions are from curiosity as to why things are not working as you expected, I fully appreciate that.
If your questions are
because you think there is a significant advantage in using static
libraries and section garbage collection in your build process, I
believe it is unlikely to be beneficial in reality - so it does not
matter if they don't work.
In the end, however, my guess is just that the limited coff/pe format
used by Windows binaries is the issue.
They can be helpful in some ways for omitting code and data that is
defined in the code, but not actually used in the executable. But
they can also make linking slower, and "-fdata-sections" can reduce
optimisations (especially if you have "-fcommon", which was the
default in older gcc).
In the end, however, my guess is just that the limited coff/pe
format used by Windows binaries is the issue.
Ok.
I don't think this is a pure C programming question, but it's related.
I'm building a static library mylib.a with all the object files
except main.o, and the final executable linking together main.o and
mylib.a.
I want to remove from the final exe everything present in mylib.a
that is not used in main.o.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are
defined in mod1.c. main() is the only function in main.c and only
foo1() is called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in
WSL doesn't.
Why?
On Thu, 28 Aug 2025 18:12:52 +0200
pozz <pozzugno@gmail.com> wrote:
I don't think this is a pure C programming question, but it's
related.
I'm building a static library mylib.a with all the object files
except main.o, and the final executable linking together main.o and mylib.a.
I want to remove from the final exe everything present in mylib.a
that is not used in main.o.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are
defined in mod1.c. main() is the only function in main.c and only
foo1() is called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o
mylib.a objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in
WSL doesn't.
Why?
I investigated it a little more and found two things:
1. The problem caused by gcc compiler rather than by gnu ld
linker. If you link MSVC-generated object files with gnu ld then
"garbage collection" works as expected.
2. The problem is related to gcc implementation of SEH.
Compile to asm, edit asm removing SEH directives then assemble to .o
and it works as expected.
Now in order to continue from here I'd have to know much more
about SEH than I actually do. So, I stopped.
On Mon, 1 Sep 2025 11:28:15 +0200
pozz <pozzugno@gmail.com> wrote:
In the end, however, my guess is just that the limited coff/pe
format used by Windows binaries is the issue.
Ok.
I find David Brown's explanation extremely unlikely.
Microsoft's linker also generates COFF/PE format and it never had
problems with linking in only the necessary stuff. They don't call it by fancy half-misleading names like 'garbage collection', in their world
it is simply 'link' - a default "Release' policy since forever.
If right now it does not work with Gnu ld then it happens most likely
because COFF/PE is of low priority for Gnu ld devs rather than because COFF/PE is "limited".
On 01/09/2025 21:52, Michael S wrote:
On Mon, 1 Sep 2025 11:28:15 +0200
pozz <pozzugno@gmail.com> wrote:
In the end, however, my guess is just that the limited coff/pe
format used by Windows binaries is the issue.
Ok.
I find David Brown's explanation extremely unlikely.
Microsoft's linker also generates COFF/PE format and it never had
problems with linking in only the necessary stuff. They don't call
it by fancy half-misleading names like 'garbage collection', in
their world it is simply 'link' - a default "Release' policy since
forever.
If right now it does not work with Gnu ld then it happens most
likely because COFF/PE is of low priority for Gnu ld devs rather
than because COFF/PE is "limited".
It is certainly plausible that it is the GNU ld support for COFF/PE
that is limited here, rather than the COFF/PE format itself. I don't
know enough details about the formats or the workings of GNU ld to
judge.
All I can say for sure is that the manual page for GNU ld says that
garbage collection is "experimental" for COFF/PE targets, while it
has worked fine for decades with elf formats. And that difference in formats looks like it is the root of Pozz's observations.
That may be because of a lack of development priority in GNU ld for
COFF/PE (though it supported COFF from before ELF was developed).
After all, standard COFF /is/ severely limited in many ways
(including the maximum number of sections - which will obviously be
very large when -ffunction-sections and -fdata-sections are used),
which is why most toolchain and OS vendors moved through various
proprietary extensions to COFF before dropping it altogether for ELF.
MS developed their own format PE as an extension and hybrid that grew
out of COFF, and have added more and more features to it over the
years. It is entirely believable to me that MS's own tools have
better support for more advanced use of COFF/PE than GNU's.
Il 29/08/2025 15:04, David Brown ha scritto:
On 29/08/2025 12:39, pozz wrote:
Il 29/08/2025 11:05, David Brown ha scritto:
On 28/08/2025 18:12, pozz wrote:
I don't think this is a pure C programming question, but it's related. >>>>>
I'm building a static library mylib.a with all the object files
except main.o, and the final executable linking together main.o and >>>>> mylib.a.
My first question is "Why?" Why not simply link all the object
files together?
Because I want to start creating tests on my projects and one simple
approach is what I have described. All is in a static library (a
collection of object files), except main.o where is only main().
If I want to create test1.c (with its main), I have to only link
test1.o with library.
The only "benefit" you get from using a library in this situation is
that you might conceivably save a couple of lines in your makefile,
Could you explain?
Actually I'm using cmake and I write something similar to this for each test:
add_executable(testA tests/testA.c)
target_link_libraries(testA PRIVATE ${PRJLIB})
target_link_options(testA PRIVATE -Wl,--gc-sections) # doesn't work
Without the library I need to explictly link testA.c with the exact
source files required for the test. I should take care of compilation options, because they should be the same for the main executable and the test executable (otherwise I could test a different thing). Linking
against the library helps on this point, because you are sure your
testing exactly the production binary.
and if you are using spinning rust drives and a PC from the 1990's,
you might save a second or two from the build. It is not worth the
bother.
No, it's not for that I'm using static library approach for testing.
I want to remove from the final exe everything present in mylib.a
that is not used in main.o.
My second question is "Why?" When you are working on embedded
targets, saving space like this in the executable is often a very
good idea. On a PC, it is rarely worth the effort.
This question was born because I found another problem.
I have a library distributed in source codes. One function in one
source code needs to access a global array that *must* be defined
somewhere in the project.
Okay.
As I wrote, I'm creating some tests. Not all the tests use that
function, so I thought it would be safe to not have the definition of
the global array, but this isn't true in my project and building
system. The linker complains because it doesn't find the global array.
I expected the unused function, with its references, would have been
removed by the linker.
The "--gc-sections" gnu linker option works for elf files, but is
"experimental" for coff/pe. Maybe it simply doesn't work as
effectively for mingw, which will be generating Windows-style coff/pe
binaries, while it works for WSL which uses Linux-style elf binaries.
Ok, I expected it was a very simple task for a linker. Don't put an
unused section in the final binary.
But while I appreciate that you expected linker garbage collection to
work here, you still haven't answered why you feel it is important.
(If you are just trying to understand why it doesn't work, that's fine
by me.)
I explained below. Anyway I know of countermeasures to solve the
specific problem, but my original question is only to understand what
was happening and if I was wrong in something.
Again, I thought the linker garbace collector was a simple task to do.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are
defined in mod1.c. main() is the only function in main.c and only
foo1() is called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o mylib.a >>>>> objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc
in WSL doesn't.
Why?
Why are you using "-ffunction-sections" and "-fdata-sections" ?
Because each function is in its section and can be removed if unused
by the garbage collector of the linker (at least, so I understood).
They are potentially useful if you have a significant amount of extra
code and/or data that is in your source code and not wanted in the
final binary, /and/ that it is important for the binary to be as small
as reasonably possible.
Indeed they are used in embedded world, where the program memory is
limited.
As I understand it, you have an embedded program with lots of source
code, and you want to test different parts of it by compiling with
different small "main" functions on a PC. I am not sure if you said
the main program was for an embedded system, or if I am assuming that
because you are one of the few people keeping comp.arch.embedded alive
by starting new threads there :-)
You have some relationship with Sherlock Homes :-)
Yes, you described my situation very well. I have the principal main for production exe (embedded target) and a few test mains.(native for dev machine).
For the main program, function and data sections are probably not
needed because you the source code that you build for the project is
needed for the program - if there was a lot that you didn't need, it
wouldn't be in the project build.
Indeed "-ffunction-sections" and "-fdata-sections" aren't important for
main target main.c.
For the test programs, function and data sections are not needed
because the size of the test binaries on the PC is irrelevant.
Of course, except when there are some functions that I'm not testing and that need some references that are defined in the main main(), but not
in the test main().
Again - if your questions are from curiosity as to why things are not
working as you expected, I fully appreciate that.
Yes, mainly my question was for curiosity. I already fixed my test by defining unreference data in the test main, even if it isn't really
needed in the test.
If your questions are because you think there is a significant
advantage in using static libraries and section garbage collection in
your build process, I believe it is unlikely to be beneficial in
reality - so it does not matter if they don't work.
I think now is clear. I needed linker garbage collector to produce test binary just to fix the undeclared error.
Regarding the benefecial of building a static library to link with main main.c and test main.c, I think it's a good approach yet.
In the end, however, my guess is just that the limited coff/pe format
used by Windows binaries is the issue.
Ok.
They can be helpful in some ways for omitting code and data that is
defined in the code, but not actually used in the executable. But
they can also make linking slower, and "-fdata-sections" can reduce
optimisations (especially if you have "-fcommon", which was the
default in older gcc).
On Tue, 2 Sep 2025 10:50:55 +0200
David Brown <david.brown@hesbynett.no> wrote:
On 01/09/2025 21:52, Michael S wrote:
On Mon, 1 Sep 2025 11:28:15 +0200
pozz <pozzugno@gmail.com> wrote:
In the end, however, my guess is just that the limited coff/pe
format used by Windows binaries is the issue.
Ok.
I find David Brown's explanation extremely unlikely.
Microsoft's linker also generates COFF/PE format and it never had
problems with linking in only the necessary stuff. They don't call
it by fancy half-misleading names like 'garbage collection', in
their world it is simply 'link' - a default "Release' policy since
forever.
If right now it does not work with Gnu ld then it happens most
likely because COFF/PE is of low priority for Gnu ld devs rather
than because COFF/PE is "limited".
It is certainly plausible that it is the GNU ld support for COFF/PE
that is limited here, rather than the COFF/PE format itself. I don't
know enough details about the formats or the workings of GNU ld to
judge.
All I can say for sure is that the manual page for GNU ld says that
garbage collection is "experimental" for COFF/PE targets, while it
has worked fine for decades with elf formats. And that difference in
formats looks like it is the root of Pozz's observations.
That may be because of a lack of development priority in GNU ld for
COFF/PE (though it supported COFF from before ELF was developed).
After all, standard COFF /is/ severely limited in many ways
(including the maximum number of sections - which will obviously be
very large when -ffunction-sections and -fdata-sections are used),
which is why most toolchain and OS vendors moved through various
proprietary extensions to COFF before dropping it altogether for ELF.
MS developed their own format PE as an extension and hybrid that grew
out of COFF, and have added more and more features to it over the
years. It is entirely believable to me that MS's own tools have
better support for more advanced use of COFF/PE than GNU's.
As mentioned in my other message above, it turned out that gnu ld is
not at fault. The problem is on compiler's (gcc) side. More
specifically, the problem is somehow related to gcc implementation of asynchronous unwind tables. Format of the tables appears to be
different between gcc-Linux, gcc-Windows and MSVC-Windows. I don't
think that somebody would be surprised if the 2nd combo is the least deep-thought and least well-tested between the three.
The machinery is hidden behind barely documented 'gnu as' directives
like .seh_proc and .seh_endproc so pointing to exact mistake is not
easy.
Luckily for OP, disabling generation of asynchronous unwind tables *is*
easy.
On Mon, 1 Sep 2025 11:28:15 +0200
pozz <pozzugno@gmail.com> wrote:
In the end, however, my guess is just that the limited coff/pe
format used by Windows binaries is the issue.
Ok.
I find David Brown's explanation extremely unlikely.
Microsoft's linker also generates COFF/PE format and it never had
problems with linking in only the necessary stuff. They don't call it by fancy half-misleading names like 'garbage collection', in their world
it is simply 'link' - a default "Release' policy since forever.
If right now it does not work with Gnu ld then it happens most likely
because COFF/PE is of low priority for Gnu ld devs rather than because COFF/PE is "limited".
Are you sure ... <skip>
On Tue, 2 Sep 2025 02:02:20 +0300
Michael S <already5chosen@yahoo.com> wrote:
On Thu, 28 Aug 2025 18:12:52 +0200
pozz <pozzugno@gmail.com> wrote:
I don't think this is a pure C programming question, but it's
related.
I'm building a static library mylib.a with all the object files
except main.o, and the final executable linking together main.o and
mylib.a.
I want to remove from the final exe everything present in mylib.a
that is not used in main.o.
Suppose only mod1.o is present in mylib.a. foo1() and bar1() are
defined in mod1.c. main() is the only function in main.c and only
foo1() is called from main().
gcc -O2 -ffunction-sections -fdata-sections -c -o mod1.o mod1.c
ar rcs mylib.a mod1.o
gcc -O2 -ffunction-sections -fdata-sections -c -o main.o main.c
gcc -Wl,--gc-sections,--print-gc-sections -o main[.exe] main.o
mylib.a objdump -d main[.exe] | grep bar1
MinGW in Windows build a main.exe that contains bar1(), while gcc in
WSL doesn't.
Why?
I investigated it a little more and found two things:
1. The problem caused by gcc compiler rather than by gnu ld
linker. If you link MSVC-generated object files with gnu ld then
"garbage collection" works as expected.
2. The problem is related to gcc implementation of SEH.
Compile to asm, edit asm removing SEH directives then assemble to .o
and it works as expected.
Now in order to continue from here I'd have to know much more
about SEH than I actually do. So, I stopped.
I still don't know much about SEH, but now, due to Stack Overflow, I
know how to get rid of it.
Just add -fno-asynchronous-unwind-tables to your compilation options
and suddenly 'garbage collection' works.
Of course, it helps only if you don't care about SEH. But, considering
that what you are doing are mere unit tests, I don't see why would you possibly care about it.
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,066 |
Nodes: | 10 (0 / 10) |
Uptime: | 184:50:51 |
Calls: | 13,709 |
Calls today: | 1 |
Files: | 186,950 |
D/L today: |
2,578 files (741M bytes) |
Messages: | 2,416,181 |