• Re: Correct objcopy Usage (was Re: C23 thoughts and opinions)

    From Lawrence D'Oliveiro@21:1/5 to bart on Tue Jun 4 04:33:36 2024
    On Sat, 1 Jun 2024 11:24:20 +0100, bart wrote:

    Here's my transcript:

    Here’s how to do it. To create the blob object from the blob file
    (replace «blobfile» with the file name as appropriate):

    BLOBFILE=«blobfile»
    objcopy -I binary -O elf64-x86-64 \
    --redefine-sym _binary____$(basename $BLOBFILE)_start=blob_start \
    --redefine-sym _binary____$(basename $BLOBFILE)_end=blob_end \
    --redefine-sym _binary____$(basename $BLOBFILE)_size=blob_size \
    $BLOBFILE blob.o

    Then compile and link blob.o against this example mainline:

    #include <stdio.h>
    #include <stdint.h>

    extern uint8_t blob_start;
    extern uint8_t blob_end;
    /* extern uint8_t blob_size; */

    int main()
    {
    fprintf(stdout, "start = %p\n", &blob_start);
    fprintf(stdout, "end = %p\n", &blob_end);
    fprintf(stdout, "size = %d\n", &blob_end - &blob_start);
    return 0;
    } /*main*/

    (There’s a warning which I’m ignoring for now.) Then run and see if
    the results are what you expect.

    Note I haven’t figured out how to use the “blob_size” symbol. It
    appears, seemingly correctly, as an absolute symbol in a dump by “nm”,
    but any attempt to reference it from the C code produces relocation
    errors.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Tim Rentsch on Thu Jun 6 14:56:33 2024
    On Sat, 01 Jun 2024 17:22:57 -0700
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    scott@slp53.sl.home (Scott Lurndal) writes:

    Tim Rentsch <tr.17687@z991.linuxsc.com> writes:

    bart <bc@freeuk.com> writes:

    On 01/06/2024 02:25, Scott Lurndal wrote:

    bart <bc@freeuk.com> writes:

    Little of this seems to work, sorry. You guys keep saying, do
    this, do that, no do it that way, go RTFM, but nobody has shown
    a complete program that correctly shows the -size symbol to be
    giving anything meaningful.

    If I run this: [attempt to reproduce example]

    $ cat /tmp/m.c
    #include <stdio.h>
    #include <stdint.h>

    extern uint64_t _binary_main_cpp_size;
    extern uint8_t *_binary_main_cpp_start;
    extern uint8_t *_binary_main_cpp_end;

    int main()
    {
    printf("%p\n", &_binary_main_cpp_size);
    printf("%p\n", &_binary_main_cpp_start);
    printf("%p\n", &_binary_main_cpp_end);
    return 0;
    }
    $ objcopy -I binary -B i386 -O elf64-x86-64 main.cpp /tmp/test.o
    $ cc -o /tmp/m /tmp/m.c /tmp/test.o
    $ /tmp/m
    0x30e2
    0x601034
    0x604116
    $ nm /tmp/m | grep _binary_main
    0000000000604116 D _binary_main_cpp_end
    00000000000030e2 A _binary_main_cpp_size
    0000000000601034 D _binary_main_cpp_start
    $ wc -c main.cpp
    12514 main.cpp
    $ printf 0x%x\\n 12514
    0x30e2

    The size symbol requires no space in the resulting
    executable memory image, and it's more convenient than
    having to do the math (at run time, since the compiler
    can't know the actual values).

    Here's my transcript:

    -------------------------------------
    C:\c>copy hello.c main.cpp # create main.cpp, here it's
    70 bytes 1 file(s) copied.

    C:\c>type m.c # exact same code as yours
    #include <stdio.h>
    #include <stdint.h>

    extern uint64_t _binary_main_cpp_size;
    extern uint8_t *_binary_main_cpp_start;
    extern uint8_t *_binary_main_cpp_end;

    int main()
    {
    printf("%p\n", &_binary_main_cpp_size);
    printf("%p\n", &_binary_main_cpp_start);
    printf("%p\n", &_binary_main_cpp_end);
    return 0;
    }

    C:\c>objcopy -I binary -O elf64-x86-64 main.cpp test.o # make
    test.o
    C:\c>gcc m.c test.o -o m.exe # build m executable

    C:\c>m # run m.exe
    00007ff5d5480046 # and the size is ...
    00007ff715492010
    00007ff715492056

    [similar results under WSL]

    For what it's worth I see the same behavior running on linux.

    Which versions? It works fine on my linux system (FC20, GCC
    4.8.3)

    gcc --version gives 'gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0'

    It looks like the culprit is gcc, which apparently relocates
    the symbol even though it is marked with an A type.

    gcc doesn't do 'relocations'. If you have a problem, it's
    likely with binutils (i.e. ld(1)).


    Except that typically on Linux gcc and clang use the same linker.

    I expect you are right. I run ld directly only rarely, and
    certainly am no expert. In my tests I was simply blindly
    following the example shown in your posting (with some variations
    after my attempts gave the wrong answer, trying to get it to
    work). It didn't occur to me to consider ld.

    Using clang for the final link step always gave the right answer,
    if I remember correctly.

    I reproduced your findings. The difference between gcc and clang is not
    in ld, but in ld invocation options.
    Specifically, gcc calls ld with -pie, clang calls ld without it.
    gcc default behaviour can be overwritten with -no-pie switch.
    I suppose that gcc4 has the same default as clang.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Michael S on Thu Jun 6 07:44:47 2024
    Michael S <already5chosen@yahoo.com> writes:

    On Sat, 01 Jun 2024 17:22:57 -0700
    Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:

    [..differences in gcc and clang that might be explained by ld...]

    I expect you are right. I run ld directly only rarely, and
    certainly am no expert. In my tests I was simply blindly
    following the example shown in your posting (with some variations
    after my attempts gave the wrong answer, trying to get it to
    work). It didn't occur to me to consider ld.

    Using clang for the final link step always gave the right answer,
    if I remember correctly.

    I reproduced your findings. The difference between gcc and clang is not
    in ld, but in ld invocation options.
    Specifically, gcc calls ld with -pie, clang calls ld without it.
    gcc default behaviour can be overwritten with -no-pie switch.
    I suppose that gcc4 has the same default as clang.

    Makes sense. Thank you for the explanation.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)