Assembly linking



  • Source code:

    Commands:

    as -32 -g --fatal-warnings -o basic.o basic.s
    as -32 -g --fatal-warnings -o basic_linux.o basic_linux.s
    as -32 -g --fatal-warnings -o noop.o noop.s
    ld -melf_i386 -o noop --start-group basic.o basic_linux.o noop.o
    

    Output:

    basic.o: In function `_start':
    basic.s:142: undefined reference to `size_of_Main'
    basic_linux.o: In function `runtime.output':
    basic_linux.s:13: undefined reference to `offset_of_String.length'
    basic_linux.s:14: undefined reference to `offset_of_Int.value'
    basic_linux.s:15: undefined reference to `offset_of_String.str_field'
    

    I can't figure out why I'm getting these errors. Shouldn't --start-group make the symbols show up to all of them?



  • According to objdump the only two symbols containing offset emitted by noop.o are data_offset and tag_offset (as UND, which makes sense). None of the symbols that you define with .globl and .set show up as far as I can see.

    So, given that + a quick google later, lands me on here. Apparently you can't combine .global with .set; at least those symbols will not get exported to the object file.

    Edit: Unfortunately, the solution proposed by the SO answer doesn't apply to your case, and the other "answers" are rubbish.

    Also see this. Apparently what you're trying to do is not supported by the linker formats on linux.



  • Well, don't ask @blakeyrat for help, he'll start talking about what you ned to include in the manifest section and how to compile the C# file to MSIL, and you'd both be confused.

    Filed Under: randomly overloading established jargon FTW



  • Fixed it by making this file:

    And then shoving .include "basic_defs.s" at the top of every .s file.



  • Er, I just saw this again and realized I forgot to ask: it this a set of offsets into a data structure, and if so, why didn't you use the .struct directive to simplify setting the offset labels? Yes, GAS .struct syntax is ugly, but still better than explicitly setting the field positions, I would think.



  • how is 0( \+ 4){x} better than 4*x?



  • Za? I have no idea what that syntax is from; it looks like Haskell, but... ?

    I was thinking in terms of something like

             .struct 0
    gc_object:
    gc_obj_tag:
             .struct gc_obj_tag + 4
    gc_obj_size
             .struct gc_obj_size + 4
    gc_obj_ref
             .struct gc_obj_ref + 4
    gc_obj_data
             .struct gc_obj_ref + 4
    gc_object_end:
    .set gc_object_length, gc_object_end - gc_object
    

    Yes, it is more verbose, yes it is really terrible, yes it doesn't give you proper structure fields, but it is more explicitly a structure, and (IMO) less likely to give you trouble if, for example, you end up adding a field that is 10 bytes long instead of 4 some time in the future.

    Perhaps I am missing some detail here, though. In the end, it's your decision, I was just curious about the particular choice.



  • @ScholRLEA said:

    that syntax

    The left is a regular expression. The right is a literal string. Feel free to put a number in instead of x.

    @ScholRLEA said:

    gc_object_length

    But that's not the length of an object. The length is 3 words plus size_offset(%eax) bytes.



  • Ah, I think I see my confusion, now. OK. If I am following what you are saying, you are using a variable-sized data structure, where the data beginning at data_offset is of size size_offset(%eax), right?


Log in to reply