Page 2 of 2 FirstFirst 12
Results 31 to 41 of 41

Thread: miniCRUSH 1.00

  1. #31
    Member Skymmer's Avatar
    Join Date
    Mar 2009
    Location
    Russia
    Posts
    681
    Thanks
    38
    Thanked 168 Times in 84 Posts
    Quote Originally Posted by comp1 View Post
    Also, I did not modify the source. If modifications occured, the compiler did it.
    If so, then there is only one compiler which could make this - the Intel Compiler. Am I right?

    EDIT: No, its not the Intel Compiler. Its the Matt Pietrek
    Last edited by Skymmer; 8th March 2016 at 06:45.

  2. Thanks:

    Mike (8th March 2016)

  3. #32
    Member nikkho's Avatar
    Join Date
    Jul 2011
    Location
    Spain
    Posts
    546
    Thanks
    219
    Thanked 164 Times in 105 Posts
    Quote Originally Posted by comp1 View Post
    I don't know what WinAPI is.
    And I think you are not interested in learning. If so, your modifications will be a shared knowledge, and everyone interested will learn from each other.

  4. #33
    Member
    Join Date
    May 2012
    Location
    United States
    Posts
    324
    Thanks
    182
    Thanked 53 Times in 38 Posts
    First things first, I officially concede. Congratulations Skymmer. You have clearly won this competition and I have reached a point where I can't continue. Thank you for making this a fun competition. Maybe some day I'll come back to this and attempt to continue.

    Secondly, algorithm, good job on your Linux builds! I do not have Linux and thus I can not test it but I wanted to recognize your achievement as well.

    Thirdly, nikkho, I've tried to ignore your comments but it has gotten unnecessary.

    1) You come to Skymmer's rescue and defend him as if you were married to him. In which post throughout this entire thread has he shared the way he achieves his extremely small builds?

    2) Please read: http://encode.su/threads/2321-FLIF-F...e-Format/page4. In December of 2015, Skymmer posted a special build of FLIF and when asked to share his source, he never did. He has had many months to do so.

    3) You say I am not interested in learning? What have you contributed to this thread? What have you learned from trying different compilers, searching the web on compilation techniques, etc.? I would say my friend that you are the one who appears not at all interested in learning--you want to be told how to do something and avoid the work.

    4) You have been here since 2011, and I since 2012, start using Google, reading some books, etc. and stop expecting others to do everything for you...(Except for Skymmer of course, he gets a pass from you). I can point to various occasions in the past where I was like you so I understand, but too many years have passed for you to have not progressed enough to allow you to stop having your feelings hurts when people don't do things for you and expect you to learn.

    When I started this thread and felt I had achieved something quite good, Skymmer showed me that it could be better time and time again. Thank you Skymmer for showing me that with more work and time dedicated to learning, more could be achieved.

    So once more: Thank you Skymmer and algorithm for making this a fun, competitive, motivating thread.

  5. #34
    Member
    Join Date
    Apr 2015
    Location
    Greece
    Posts
    69
    Thanks
    32
    Thanked 22 Times in 15 Posts
    For anyone wanting to reproduce my builds ,they were compiled using
    Code:
    gcc -Os -Wl,--gc-sections -Wl,--build-id=none -fmerge-all-constants crush.cpp
    for 64bit (yes gcc not g++.clang produces larger binaries)
    Code:
    gcc -Os -Wl,--gc-sections -Wl,--build-id=none -fmerge-all-constants -m32 crush.cpp
    for 32bit

    then run sstrip a.out (you can download it from here http://www.muppetlabs.com/~breadbox/...lfkickers.html)

    For even smaller file remove the two fclose as they are not needed,the last line that prints execution time and
    the first line from main that calls clock which is also not needed as now it does not calculate execution time

    For faster binaries replace putc with putc_unlocked and getc with getc_unlocked (not used in my previous binaries uploaded here)

    I also replaced stuff like
    Code:
    put_bits(2, 1<<1); // 01
    put_bits(B_BITS, l-A);
    to
    Code:
    put_bits(B_BITS+2, ((l-A)<<2)|(1<<1));

    For even faster decompression maybe(I have not tested it) it is better to replace
    Code:
                    if (get_bits(1))
                         len=get_bits(A_BITS);
                    else if (get_bits(1))
                        len=get_bits(B_BITS)+A;
                    else if (get_bits(1))
                        len=get_bits(C_BITS)+B;
                    else if (get_bits(1))
                        len=get_bits(D_BITS)+C;
                    else if (get_bits(1))
                        len=get_bits(E_BITS)+D;
                    else
                        len=get_bits(F_BITS)+E;
    with a 32 entry look up table like huffman decoders
    Last edited by algorithm; 8th March 2016 at 21:11.

  6. Thanks:

    nikkho (8th March 2016)

  7. #35
    Member nikkho's Avatar
    Join Date
    Jul 2011
    Location
    Spain
    Posts
    546
    Thanks
    219
    Thanked 164 Times in 105 Posts
    Thank you very much for your kind words comp1.

    Quote Originally Posted by comp1 View Post
    Thirdly, nikkho, I've tried to ignore your comments but it has gotten unnecessary.
    Yes, my coments were as much unnecessary as doing things without sharing you Visual C++ modified projects not your ideas. Agree.

    Quote Originally Posted by comp1 View Post
    1) You come to Skymmer's rescue and defend him as if you were married to him. In which post throughout this entire thread has he shared the way he achieves his extremely small builds?
    I am free, and can defend the positions I want. To be honest Skymmer was the only one giving a clue of what he did, linking dynamically to VC++ runtimes. Same as algorithm did. On the other side, you lied by saying source was the same, when you then admited a line was removed. Just an example.

    Quote Originally Posted by comp1 View Post
    2) Please read: http://encode.su/threads/2321-FLIF-F...e-Format/page4. In December of 2015, Skymmer posted a special build of FLIF and when asked to share his source, he never did. He has had many months to do so.
    Was not a part of this thread. Maybe he did not do well, and if so, I will not defend him on that thread for sure.

    Quote Originally Posted by comp1 View Post
    3) You say I am not interested in learning? What have you contributed to this thread? What have you learned from trying different compilers, searching the web on compilation techniques, etc.? I would say my friend that you are the one who appears not at all interested in learning--you want to be told how to do something and avoid the work.
    If you were interested, you would share your knowledge, and let Skymmer improve over your work, and then you will improve over him, and probably in the whole thing, I would learn something about the old Visual C++ 6.
    I have not contributed to the this thread, other than encouraging your to share.
    But have contributed a lot in here: http://encode.su/threads/1589-FileOptimizer even posting full sources, as you can see, in order to benefict others, and not only my ego.

    Quote Originally Posted by comp1 View Post
    4) You have been here since 2011, and I since 2012, start using Google, reading some books, etc. and stop expecting others to do everything for you...(Except for Skymmer of course, he gets a pass from you). I can point to various occasions in the past where I was like you so I understand, but too many years have passed for you to have not progressed enough to allow you to stop having your feelings hurts when people don't do things for you and expect you to learn.
    Refer to 3, or other publicly available open source projects. Maybe if you do, you could guess how much Google (I prefer duckduckgo in fact), books, papers, and research I have done. But what is more important, I also compiled the projects I coded, and of course, shared the code and the projects. Not was limited to compiling other's projects.

    Quote Originally Posted by comp1 View Post
    When I started this thread and felt I had achieved something quite good, Skymmer showed me that it could be better time and time again. Thank you Skymmer for showing me that with more work and time dedicated to learning, more could be achieved
    That is what I like from a community, learn from others, and learn to others.

  8. #36
    Member Skymmer's Avatar
    Join Date
    Mar 2009
    Location
    Russia
    Posts
    681
    Thanks
    38
    Thanked 168 Times in 84 Posts
    nikkho, thanks for your support and your words. And especially thanks for been speaking openly. This is what I respect.
    comp1, thanks for your words too and thanks for starting this thread. Without it I would never invent one of the tricks I used.
    algorithm, thanks for participating in this chaotic competition. I was never familiar with ELF format and never knew that something similar is possible in Linux.

    I decided to completely describe the methods I used to achieve such size of executable. By the way, its 3686 bytes now.
    Please note that my method brings almost nothing new and it doesn't pretends to be the best possible minimization method.

    crush v1.00 in 3686 bytes without PE compression
    1.) Visual Studio 6.0 as compiler and linker
    Yes, I'm aware of the magic linker by Mentor\Blueberry and it was used for experimental version of crush but we decided to go with pure methods without any compression so thats why we'll use MSVS 6.0 for both compiling and linking steps.
    Actually getting the copy of MSVS 6 nowadays is a big problem. I mean getting the legal copy. MSVS 6 is not sold for a long time so if you don't have a dusty disk lying somewhere in garbage depths of your garage then you're in serious trouble.
    MSVS 6 is easily can be installed on modern OSes (at least on Win7x64) but keep in mind that in some cases installation is not possible. To make it possible please be sure that your TEMP folder exists and you don't have some small-sized virtual disks mounted. MSVS installer sometimes tries to put its temporary files to such disks and for some reasons fails.
    Please note that Service Pack 6 exists for MSVS 6 and it can be downloaded from here.
    Also note that if you're stuck with updates then acmsetup /T sp698ent.stf will help you. After all preparations you must end up with following versions:
    Compiler (cl.exe): 12.00.8804
    Linker (link.exe): 6.00.8447

    2.) Source modification
    The main reason to modify the source is not the wish of minimization but compatibility. Sad but true - MSVS 6 is not compatible with _ftelli64
    More exactly speaking stdio.h from MSVS 6 is not aware of _ftelli64
    Thats why we need to get rid of it. But wait! There is a FTELLI64.C and INTERNAL.H exist. Sure. Feel free to try put em into mix
    Also. After some investigations I came to conclusion that _ftelli64 never was a part of msvcrt.dll so I think that dynamic compiling against msvcrt.dll and _ftelli64 are mutually exclusive. But I can't say for sure.
    So this time we simply comment the following:

    // #include <time.h>

    // const clock_t start=clock();

    // printf("%lld -> %lld in %gs\n", _ftelli64(in), _ftelli64(out),
    // double(clock()-start)/CLOCKS_PER_SEC);

    // fclose(in);
    // fclose(out);

    And here comes another problem - the problem of "loop-scope". More exactly speaking MSVS 6 follows some older C++ specs and doesn't allows redefinitions of variables inside the loop. On practise:


    while ((size=fread(buf, 1, BUF_SIZE, in))>0)
    {
    fwrite(&size, 1, sizeof(size), out);

    for (int i=0; i<HASH1_SIZE+HASH2_SIZE; ++i) // not acceptable
    head[i]=-1;

    int h1=0;
    int h2=0;
    for (int i=0; i<HASH1_LEN; ++i) // not acceptable
    h1=update_hash1(h1, buf[i]);
    for (int i=0; i<HASH2_LEN; ++i) // not acceptable
    h2=update_hash2(h2, buf[i]);

    And this one is correct for MSVS 6


    int i=0;
    while ((size=fread(buf, 1, BUF_SIZE, in))>0)
    {
    fwrite(&size, 1, sizeof(size), out);

    for (i=0; i<HASH1_SIZE+HASH2_SIZE; ++i)
    head[i]=-1;

    int h1=0;
    int h2=0;
    for (i=0; i<HASH1_LEN; ++i)
    h1=update_hash1(h1, buf[i]);
    for (i=0; i<HASH2_LEN; ++i)
    h2=update_hash2(h2, buf[i]);

    In later versions of MSVS such problem can be solved by simply using /Zc:forScope option.

    3.) LIBCTINY
    The idea of LIBCTINY is to substitute some functions and code with WinAPI equivalents (though there are some more tricks behind the scene). It allows really radical decrease of code size without too much efforts.
    LIBCTINY have been created by Matt Pietrek and can be found here.
    To use it simply put libctiny.lib somewhere in your LIB search folder (or use linker option for direct pointing) and add the following to your linker options: -nodefaultlib libctiny.lib required_libs
    More details in next section.

    4.) Compiler and linker options
    Below is the list of compiler and linker options I have used. Please note that:
    - these options are not guaranteed to give the smallest size for every source
    - for best results you should try almost all permutations
    - some options accept disabling by adding minus sign after option itself even if its not indicated in manual and\or console output
    - some options are on or off by default so my command line can be quite redundant but for me its better to control all of them
    - effect of some options cannot be judged by resulting exe size. The size of the OBJ is better sometimes but it's also not the best factor )

    Compiler options (and compiler options which affect linker)
    Code:
    -nologo          good option
    -Oy              omit frame pointer, makes code smaller, makes OBJ larger by adding debug related things
    -MD              link with MSVCRT.LIB (-ML and -MT options are worth trying too)
    -Os              favor smaller code (use -Ot for faster but larger code)
    -Og              global optimizations, makes code smaller but sometimes hurts (use -Og- to disable)
    -Ob1             inlining, -Ob0 and -Ob2 can have different effect
    -Oa              no aliasing
    -Gy              separate functions for linker, seems can give effect with linker's -opt:
    -Za -Op-         disable extensions, makes code smaller, implies -Op so we add -Op-
    -Zl              omit default library names in OBJ files
    -GR-             disable RTTI
    -GX-             disable exception handling
    -Gi-             disable incremental compilation
    -Gm-             disable minimal rebuild
    -EHs-a-c-        disable exception handling one more time
    -QIfdiv-         disable FDIV fix
    -QI0f-           disable 0x0f fix
    -Gs              disable stack checking calls
    Linker options
    Code:
    -link -nologo
    -nodefaultlib libctiny.lib kernel32.lib msvcrt.lib        no use of the default libs and use libctiny, and then search for needed references in kernel32\msvcrt
    -opt:ref                                                  eliminate functions and/or data that is never referenced
    -opt:icf,3                                                perform identical COMDAT folding with 3 iterations (can give no effect)
    -filealign:0x200                                          undocumented option, sets physical section align (DON'T MESS WITH -align)
    -subsystem:console                                        controls the type of the entry point code and some other stuff
    -incremental:no                                           disable incremental linking
    Some other options to note (especially string pooling options which can give a serious effect sometimes)
    Code:
    -Oi
    -GF
    -Gf
    -G<3|4|5|6|B>
    -GA
    -J
    5.) Sections merging, linker tricks and yoda's final strike
    OK, we have a three sections in our file:
    .text
    .rdata
    .data

    And this is a big problem because any section in exe file which is presumable to work in NT family should be aligned to 0x200 at minimum. Yes, this means that every section will have a size of 512 byte minimum, no matter how much of data in this section. Such PE Coff and Windows loader rules are explainable from some point of view but such rules also resulted in possibility of code injection using "sections caves". But I'm out of topic here.
    Actually not all of sections should be aligned to 0x200. Last section can avoid this rule. Its also true if the EXE has only one section.
    Another problem is the header size. Its too big and can be smaller.
    So our goal is:
    - merge all sections into one
    - eliminate section padding due align
    - make header size smaller

    In order to merge all sections into one we can use the linker's option -merge:
    For example: -merge:.rdata=.data -merge:.text=.data
    But it will not work. At least for such file. I don't know why (probably due the linker internal error) you'll get the exe size of 151 000 576 bytes. It's not the misprint. I really mean 144 MB.
    Futher tests showed up that:
    Code:
    -merge:.text=.rdata   works
    -merge:.rdata=.text   works
    -merge:.text=.data    works
    -merge:.data=.text    works
    -merge:.rdata=.data   144 MB file
    -merge:.data=.rdata   144 MB file
    The answer to this problem is that linker applies some really mad values for size of initialized data, size of image and virtual size of .data section.
    Code:
    DUMPBIN.EXE -headers crush.exe >headers.txt
    Microsoft (R) COFF Binary File Dumper Version 6.00.8447
    Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
    Dump of file crush.exe
    PE signature found
    File Type: EXECUTABLE IMAGE
    
    OPTIONAL HEADER VALUES
             9000800 size of initialized data
             9004000 size of image
    
    SECTION HEADER #3
       .data name
     9000560 virtual size
        3000 virtual address
         200 size of raw data
    But relax, we can use an interesting trick. If we instruct the linker to apply a different from standard attributes to .data section then linker creates an additional .bss section inside the exe with the following effect for us:
    - new .bss section has the zero raw size and takes zero bytes inside the exe
    - we can merge all other sections without problems
    - in total there will be two sections but .bss section takes only 40 bytes in header
    - in order to make our resulting section the last, we cannot use .text section as TO in scope of syntax -merge:FROM=TO

    Simply speaking here is the string that will do the trick: -link -section:.data,EWRX -merge:.rdata=.data -merge:.text=.data

    And finally. You need to find the yoda's some utility and use it twice (or more) with hardcore realign option.
    It will truncate the header size and will eliminate section padding.
    Hope it will be usefull to somebody. Thanks.
    Attached Files Attached Files

  9. Thanks (4):

    encode (14th March 2016),Matt Mahoney (14th March 2016),Mike (14th March 2016),nikkho (14th March 2016)

  10. #37
    Member
    Join Date
    May 2012
    Location
    United States
    Posts
    324
    Thanks
    182
    Thanked 53 Times in 38 Posts
    Quote Originally Posted by Skymmer View Post
    nikkho, thanks for your support and your words. And especially thanks for been speaking openly. This is what I respect.
    comp1, thanks for your words too and thanks for starting this thread. Without it I would never invent one of the tricks I used.
    algorithm, thanks for participating in this chaotic competition. I was never familiar with ELF format and never knew that something similar is possible in Linux.

    I decided to completely describe the methods I used to achieve such size of executable. By the way, its 3686 bytes now.
    Please note that my method brings almost nothing new and it doesn't pretends to be the best possible minimization method.

    crush v1.00 in 3686 bytes without PE compression
    1.) Visual Studio 6.0 as compiler and linker
    Yes, I'm aware of the magic linker by Mentor\Blueberry and it was used for experimental version of crush but we decided to go with pure methods without any compression so thats why we'll use MSVS 6.0 for both compiling and linking steps.
    Actually getting the copy of MSVS 6 nowadays is a big problem. I mean getting the legal copy. MSVS 6 is not sold for a long time so if you don't have a dusty disk lying somewhere in garbage depths of your garage then you're in serious trouble.
    MSVS 6 is easily can be installed on modern OSes (at least on Win7x64) but keep in mind that in some cases installation is not possible. To make it possible please be sure that your TEMP folder exists and you don't have some small-sized virtual disks mounted. MSVS installer sometimes tries to put its temporary files to such disks and for some reasons fails.
    Please note that Service Pack 6 exists for MSVS 6 and it can be downloaded from here.
    Also note that if you're stuck with updates then acmsetup /T sp698ent.stf will help you. After all preparations you must end up with following versions:
    Compiler (cl.exe): 12.00.8804
    Linker (link.exe): 6.00.8447

    2.) Source modification
    The main reason to modify the source is not the wish of minimization but compatibility. Sad but true - MSVS 6 is not compatible with _ftelli64
    More exactly speaking stdio.h from MSVS 6 is not aware of _ftelli64
    Thats why we need to get rid of it. But wait! There is a FTELLI64.C and INTERNAL.H exist. Sure. Feel free to try put em into mix
    Also. After some investigations I came to conclusion that _ftelli64 never was a part of msvcrt.dll so I think that dynamic compiling against msvcrt.dll and _ftelli64 are mutually exclusive. But I can't say for sure.
    So this time we simply comment the following:

    // #include <time.h>

    // const clock_t start=clock();

    // printf("%lld -> %lld in %gs\n", _ftelli64(in), _ftelli64(out),
    // double(clock()-start)/CLOCKS_PER_SEC);

    // fclose(in);
    // fclose(out);

    And here comes another problem - the problem of "loop-scope". More exactly speaking MSVS 6 follows some older C++ specs and doesn't allows redefinitions of variables inside the loop. On practise:


    while ((size=fread(buf, 1, BUF_SIZE, in))>0)
    {
    fwrite(&size, 1, sizeof(size), out);

    for (int i=0; i<HASH1_SIZE+HASH2_SIZE; ++i) // not acceptable
    head[i]=-1;

    int h1=0;
    int h2=0;
    for (int i=0; i<HASH1_LEN; ++i) // not acceptable
    h1=update_hash1(h1, buf[i]);
    for (int i=0; i<HASH2_LEN; ++i) // not acceptable
    h2=update_hash2(h2, buf[i]);

    And this one is correct for MSVS 6


    int i=0;
    while ((size=fread(buf, 1, BUF_SIZE, in))>0)
    {
    fwrite(&size, 1, sizeof(size), out);

    for (i=0; i<HASH1_SIZE+HASH2_SIZE; ++i)
    head[i]=-1;

    int h1=0;
    int h2=0;
    for (i=0; i<HASH1_LEN; ++i)
    h1=update_hash1(h1, buf[i]);
    for (i=0; i<HASH2_LEN; ++i)
    h2=update_hash2(h2, buf[i]);

    In later versions of MSVS such problem can be solved by simply using /Zc:forScope option.

    3.) LIBCTINY
    The idea of LIBCTINY is to substitute some functions and code with WinAPI equivalents (though there are some more tricks behind the scene). It allows really radical decrease of code size without too much efforts.
    LIBCTINY have been created by Matt Pietrek and can be found here.
    To use it simply put libctiny.lib somewhere in your LIB search folder (or use linker option for direct pointing) and add the following to your linker options: -nodefaultlib libctiny.lib required_libs
    More details in next section.

    4.) Compiler and linker options
    Below is the list of compiler and linker options I have used. Please note that:
    - these options are not guaranteed to give the smallest size for every source
    - for best results you should try almost all permutations
    - some options accept disabling by adding minus sign after option itself even if its not indicated in manual and\or console output
    - some options are on or off by default so my command line can be quite redundant but for me its better to control all of them
    - effect of some options cannot be judged by resulting exe size. The size of the OBJ is better sometimes but it's also not the best factor )

    Compiler options (and compiler options which affect linker)
    Code:
    -nologo          good option
    -Oy              omit frame pointer, makes code smaller, makes OBJ larger by adding debug related things
    -MD              link with MSVCRT.LIB (-ML and -MT options are worth trying too)
    -Os              favor smaller code (use -Ot for faster but larger code)
    -Og              global optimizations, makes code smaller but sometimes hurts (use -Og- to disable)
    -Ob1             inlining, -Ob0 and -Ob2 can have different effect
    -Oa              no aliasing
    -Gy              separate functions for linker, seems can give effect with linker's -opt:
    -Za -Op-         disable extensions, makes code smaller, implies -Op so we add -Op-
    -Zl              omit default library names in OBJ files
    -GR-             disable RTTI
    -GX-             disable exception handling
    -Gi-             disable incremental compilation
    -Gm-             disable minimal rebuild
    -EHs-a-c-        disable exception handling one more time
    -QIfdiv-         disable FDIV fix
    -QI0f-           disable 0x0f fix
    -Gs              disable stack checking calls
    Linker options
    Code:
    -link -nologo
    -nodefaultlib libctiny.lib kernel32.lib msvcrt.lib        no use of the default libs and use libctiny, and then search for needed references in kernel32\msvcrt
    -opt:ref                                                  eliminate functions and/or data that is never referenced
    -opt:icf,3                                                perform identical COMDAT folding with 3 iterations (can give no effect)
    -filealign:0x200                                          undocumented option, sets physical section align (DON'T MESS WITH -align)
    -subsystem:console                                        controls the type of the entry point code and some other stuff
    -incremental:no                                           disable incremental linking
    Some other options to note (especially string pooling options which can give a serious effect sometimes)
    Code:
    -Oi
    -GF
    -Gf
    -G<3|4|5|6|B>
    -GA
    -J
    5.) Sections merging, linker tricks and yoda's final strike
    OK, we have a three sections in our file:
    .text
    .rdata
    .data

    And this is a big problem because any section in exe file which is presumable to work in NT family should be aligned to 0x200 at minimum. Yes, this means that every section will have a size of 512 byte minimum, no matter how much of data in this section. Such PE Coff and Windows loader rules are explainable from some point of view but such rules also resulted in possibility of code injection using "sections caves". But I'm out of topic here.
    Actually not all of sections should be aligned to 0x200. Last section can avoid this rule. Its also true if the EXE has only one section.
    Another problem is the header size. Its too big and can be smaller.
    So our goal is:
    - merge all sections into one
    - eliminate section padding due align
    - make header size smaller

    In order to merge all sections into one we can use the linker's option -merge:
    For example: -merge:.rdata=.data -merge:.text=.data
    But it will not work. At least for such file. I don't know why (probably due the linker internal error) you'll get the exe size of 151 000 576 bytes. It's not the misprint. I really mean 144 MB.
    Futher tests showed up that:
    Code:
    -merge:.text=.rdata   works
    -merge:.rdata=.text   works
    -merge:.text=.data    works
    -merge:.data=.text    works
    -merge:.rdata=.data   144 MB file
    -merge:.data=.rdata   144 MB file
    The answer to this problem is that linker applies some really mad values for size of initialized data, size of image and virtual size of .data section.
    Code:
    DUMPBIN.EXE -headers crush.exe >headers.txt
    Microsoft (R) COFF Binary File Dumper Version 6.00.8447
    Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
    Dump of file crush.exe
    PE signature found
    File Type: EXECUTABLE IMAGE
    
    OPTIONAL HEADER VALUES
             9000800 size of initialized data
             9004000 size of image
    
    SECTION HEADER #3
       .data name
     9000560 virtual size
        3000 virtual address
         200 size of raw data
    But relax, we can use an interesting trick. If we instruct the linker to apply a different from standard attributes to .data section then linker creates an additional .bss section inside the exe with the following effect for us:
    - new .bss section has the zero raw size and takes zero bytes inside the exe
    - we can merge all other sections without problems
    - in total there will be two sections but .bss section takes only 40 bytes in header
    - in order to make our resulting section the last, we cannot use .text section as TO in scope of syntax -merge:FROM=TO

    Simply speaking here is the string that will do the trick: -link -section:.data,EWRX -merge:.rdata=.data -merge:.text=.data

    And finally. You need to find the yoda's some utility and use it twice (or more) with hardcore realign option.
    It will truncate the header size and will eliminate section padding.
    Hope it will be usefull to somebody. Thanks.
    I wanted to point out a couple of things:

    1) In my case, I used Visual Studio 97 (5.0).

    2) Also, Skymmer, you mentioned /Ob1. That should always be /Ob0. Inlining increases the size of the executable a lot of there is a lot of it and if the compiler can recognize it as inlining.

    For example, try your same method with ICC 11.1. Try to compile with /Ob1 and then change it to /Ob0 and you'll see a difference. In the case of CRUSH, VC6/VC5 does not recognize the "inline" statements. In VC6, you can add:

    Code:
    #define inline __forceinline
    And then use /Ob1 or /Ob2 and you will get a larger executable (few KB) and a faster performance as well. (Note that __forceinline does not work in VC5).

    3) A day or two after you posted your last build, I figured out the realignment trick. I knew that's what you were doing but manually using /FILEALIGN:1 would not allow the executable to run on Win7.

  11. #38
    Member Skymmer's Avatar
    Join Date
    Mar 2009
    Location
    Russia
    Posts
    681
    Thanks
    38
    Thanked 168 Times in 84 Posts
    Quote Originally Posted by comp1 View Post
    2) Also, Skymmer, you mentioned /Ob1. That should always be /Ob0. Inlining increases the size of the executable a lot
    You're wrong. Inlining doesn't means code size increasement as a rule of thumb. Simple proof: with -Ob0 crush.exe size is 3758 bytes.
    3758 is larger than 3686, isn't it?

  12. #39
    Member nikkho's Avatar
    Join Date
    Jul 2011
    Location
    Spain
    Posts
    546
    Thanks
    219
    Thanked 164 Times in 105 Posts
    Quote Originally Posted by Skymmer View Post
    You're wrong. Inlining doesn't means code size increasement as a rule of thumb. Simple proof: with -Ob0 crush.exe size is 3758 bytes.
    3758 is larger than 3686, isn't it?
    Agree. It depends on the size of the funcion being inline. If it is not inlined (ie called), a overhead for managing stack and passing parameters is required.

  13. #40
    Member
    Join Date
    May 2012
    Location
    United States
    Posts
    324
    Thanks
    182
    Thanked 53 Times in 38 Posts
    Quote Originally Posted by Skymmer View Post
    You're wrong. Inlining doesn't means code size increasement as a rule of thumb. Simple proof: with -Ob0 crush.exe size is 3758 bytes.3758 is larger than 3686, isn't it?
    Trey defining __forceinline in code and try /Ob0 and try /Ob1. Try with VC6 and with ICC 11.1. In my tests, this is treue for CRUSH, LZPXJ, TANGELI, UDA, etc.

    EDIT: Actually never mind. With VC6 that does not work. VC6 does not inline like ICC 11.1 does. So I guess that is not relevant here since we use VC5/VC6 to achieve smallest binaries.
    Last edited by comp1; 15th March 2016 at 01:32.

  14. #41
    Programmer Bulat Ziganshin's Avatar
    Join Date
    Mar 2007
    Location
    Uzbekistan
    Posts
    4,505
    Thanks
    741
    Thanked 665 Times in 359 Posts
    http://www.codeproject.com/Articles/...untime-Library

    googling for "Tiny C Runtime Library" reveals a lot of other resources on this topic

  15. Thanks:

    Skymmer (13th April 2016)

Page 2 of 2 FirstFirst 12

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •