crtc-demos / newlib-ia16

Newlib port for IA16
GNU General Public License v2.0
5 stars 5 forks source link

Nontrivial .com file crashes at startup -- ld calculates __lbss wrongly #2

Closed tkchia closed 7 years ago

tkchia commented 7 years ago

I wrote a simple program qux.c (linked) which just does a printf and exits. When compiled, the .com file starts

xor ax,ax
mov di, 0xb1c4
mov cx, 0xb1cb
cld
rep stosw

which crashes at the rep stosw due to a bogus BSS length (__lbss = 0xb1cb).

It seems ld got confused by the arithmetic in the expression

__lbss = ((__ebss + 1) - __sbss) / 2;

in libgloss/ia16/dos-com.ld, and thought that __lbss should be relative to some section, rather than an absolute symbol.

Changing the expression to e.g.

__lbss = (ABSOLUTE(__ebss) + 1 - ABSOLUTE(__sbss)) / 2;

or

__lbss = (__ebss + 1) / 2 - __sbss / 2;

should fix the problem.

And, thank you very much for your gcc port! :)

reenigne commented 7 years ago

Thanks for the analysis! Coincidentally, I was actually investigating this exact problem today, though I came up with a different fix, just splitting up the calculation:

    __lbss0 = __ebss - __sbss;
    __lbss1 = __lbss0 + 1;
    __lbss = __lbss1 / 2;

I'll commit this momentarily so that it will be fixed in the next release.

I think this is an actual linker bug rather than a problem with being section-relative - I've been doing most of my testing with a more recent version of binutils (the one in https://github.com/crtc-demos/binutils-ia16) which doesn't have this problem, but unfortunately the Mentor Graphics release used an older version of binutils in which this wasn't fixed.

tkchia commented 7 years ago

Thank you! I await your next release. :)