On Tue, 29 Oct 2019, Guild Navigator wrote:
> Program prints first two strings directly.
> But it does not print the third string (1st array string).
>
> And debugging says why.
> The address of msg1 and msg2 is not stored correctly in the array.
> So when I access the address of msg1 from the array:
> movq array (%rip), %rsi
> it is NOT the address of msg1.
>
> I dont know if it is a linker problem?
> I could kind of do "manual relocation" of sorts to manually
> correct the addresses put in the array.
In general, if you're going to exclude all the C startup bits that the
operating system has provided, then you've signed up for handling all the
possible ELF bits yourself. If you haven't boned up on ELF and its
variations yet, then you should do so, if just so you can recognize when
stuff has gone wrong.
In particular, the OpenBSD linker defaults to PIE. To quote
clang-local(1) (similar text is in gcc-local(1)):
- clang will generate PIE code by default, allowing the system to load
the resulting binary at a random location. This behavior can be
turned off by passing -fno-pie to the compiler and -nopie to the
linker. It is also turned off when the -pg flag is used.
This means that yes, your executable has relocations. You've left out the
rcrt0.o code that OpenBSD provides that handles such relocations,
therefore you must either do the relocation processing yourself, or invoke
the linker with the -nopie flag to instead generate a staticly positioned
binary.
If you want to handle the relocations yourself, then eyeball the code in
/usr/src/lib/csu/, particularly boot.h and amd64/md_init.h, and read the
ELF spec and the amd64 ABI spec for structure definitions and similar.
> But what would be the OpenBSD correct way to
> write such simple print-from-the-array-of-strings program?
The answer to that literal question is "write it in C", but you obviously
have another requirement of "...in ASM".
There are *zero* places in OpenBSD where we write pure assembler programs.
There are only two places where we do process bootstrap bits, lib/csu and
libexec/ld.so/, and for both of those we do _just_ enough ASM to make
calling a limited subset of C possible, and then call a C routine to do
self-relocation. Improving the C version of the self-relocation code is
*much* faster than trying improve N assembly versions. Heck, I did so
just this month.
ASM is cool for stuff that C can't do, but if C can do it the developer's
time (and the time of future openbsd maintainers!) is much better spent in
C than in ASM. I've touched ASM on every single current OpenBSD arch, so
I understand the high cost of doing that when it _has_ been necessary and
I have no interest in borking around in ASM for stuff C can reasonably do.
Philip Guenther