BOOTBOOT Font Linking problem

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
LyricalRain
Posts: 16
Joined: Thu Jul 01, 2021 3:24 pm

BOOTBOOT Font Linking problem

Post by LyricalRain »

I distributed the example kernel's files (kernel.cpp, bootboot.h, font.psf) across my directory structure (src, lib, Fonts) and tried to compile them. However, when it tries to link the kernel.o and the font.o, it gives me an error saying reference to "binary font psf start" is undefined. I am using the exact same commands as given in the example kernel, and they worked when the directory structure was the same as that provided on Gitlab. My question is, does the directory structure affect the linking with the font binary object file? If not, what could be the possible problem?
nexos
Member
Member
Posts: 1081
Joined: Tue Feb 18, 2020 3:29 pm
Libera.chat IRC: nexos

Re: BOOTBOOT Font Linking problem

Post by nexos »

What objdump say about your font file? Have you ran objcopy to turn it into an ELF?
"How did you do this?"
"It's very simple — you read the protocol and write the code." - Bill Joy
Projects: NexNix | libnex | nnpkg
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: BOOTBOOT Font Linking problem

Post by Octocontrabass »

LyricalRain wrote:does the directory structure affect the linking with the font binary object file?
No.
LyricalRain wrote:If not, what could be the possible problem?
Maybe you made a mistake when you updated the paths in the makefile. Are there any other errors?
monarrk
Posts: 20
Joined: Mon Nov 02, 2020 4:53 pm
Libera.chat IRC: monarrk

Re: BOOTBOOT Font Linking problem

Post by monarrk »

with objcopy, the name of the exported symbol changes depending on where the file is located. it's kinda annoying. to figure out what it is for your file, do `nm font.o` and replace the symbol name in your code with the correct one that nm outputs
monarrk
Posts: 20
Joined: Mon Nov 02, 2020 4:53 pm
Libera.chat IRC: monarrk

Re: BOOTBOOT Font Linking problem

Post by monarrk »

Octocontrabass wrote:
LyricalRain wrote:does the directory structure affect the linking with the font binary object file?
No.
Yes.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: BOOTBOOT Font Linking problem

Post by bzt »

monarrk wrote:
Octocontrabass wrote:
LyricalRain wrote:does the directory structure affect the linking with the font binary object file?
No.
Yes.
Yes, it does change the variable's name unfortunately.
monarrk wrote:with objcopy, the name of the exported symbol changes depending on where the file is located. it's kinda annoying. to figure out what it is for your file, do `nm font.o` and replace the symbol name in your code with the correct one that nm outputs
Exactly. FYI my Makefile uses ld, not objcopy, but the same.

To solve the issue, you have several options:
1. you can adjust the variable name
2. in your Makefile, you can switch directories temporarily, so that you always run "ld -b binary" (or "objcopy") in the current working directory, hence removing the path from the variable's name
3. in your Makefile, copy the file and then delete the copy (this is what I do for example here)
4. convert the binary into a C byte array (for example I do this here)

The advantage of "ld -r -b binary" (or "objcopy") is that it is fast.
The disadvantage is that path matters and it is not fully portable, doesn't work on MacOS for example and LLVM toolchain doesn't have "objcopy" (or at least it didn't had, maybe they have added it since I've last checked).

That's why I've created bin2h.c. The advantage is 100% portability, "ld" compatibility doesn't matter, no additional tool required (like "objcopy").
The disadvantage is that generating a byte array and then compiling it into binary is slower than just converting a binary into ELF (you won't notice this for a small file like a font, but for example with mkbootimg which has several megabytes of firmware files too it is noticeable). Further advantage is that you can also add compression to it if you want, I do that with mkbootimg for example.
Another version of bin2h.c can be found here. This version uses stb's compressor, and it also can convert entire directories into byte arrays recursively.

Cheers,
bzt
Last edited by bzt on Fri Jul 02, 2021 11:31 pm, edited 1 time in total.
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: BOOTBOOT Font Linking problem

Post by Octocontrabass »

bzt wrote:bin2h.c
Wouldn't it be easier (and faster) to use the incbin directive in an assembly file instead of an array in a C header?
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: BOOTBOOT Font Linking problem

Post by bzt »

Octocontrabass wrote:
bzt wrote:bin2h.c
Wouldn't it be easier (and faster) to use the incbin directive in an assembly file instead of an array in a C header?
No, not for me. Assembly isn't portable and not all compilers support inline Assembly. Adding a new language to the mix is not easier, and that's something that I deliberately wanted to avoid as it requires an additional tool in the toolchain (but I couldn't avoid it entirely with Go, because Go is a shitty, particularly badly designed language).
Right now all the mykernel examples (save Go) are only using their main language nothing else (and with Go I managed to shrink the Assembly to a single "ret" instruction which is luckily portable :-)).

But of course the OP might consider incbin, because in a real kernel you can't escape the Assembly dependency, and if so, they could just as well use it.

EDIT: here's a good collection of embedding options. It mentions using winres too that we haven't considered so far (but that only works with PE format).

Cheers,
bzt
LyricalRain
Posts: 16
Joined: Thu Jul 01, 2021 3:24 pm

Re: BOOTBOOT Font Linking problem

Post by LyricalRain »

Thank you for your replies! I thought the directory thing must be it but I couldn't pinpoint the error.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: BOOTBOOT Font Linking problem

Post by nullplan »

bzt wrote:No, not for me. Assembly isn't portable and not all compilers support inline Assembly.
Normally not, but in this case:

Code: Select all

.section ".rodata",  "a", @progbits
.global font_start
.type font_start, @object
font_start:
.incbin "font.psf"
.global font_end
.type font_end, @object
font_end:
That should work for all ELF architectures. For PE the section name would be ".rdata", which you can abstract with a preprocessor directive, as necessary. Also, name mangling can be added as necessary (which I think was only needed for 32-bit Windows, but I'm not sure about 64-bit Windows). Since the file contains no architecture specific code, any version of GNU as should be able to compile this, no matter the target architecture, and probably also some other assemblers. The C interface is "extern const char font_start[], font_end[]".

And if you need to support MSVC, the only major C compiler to not use a GNU as compatible assembler, then just add a second version for MSVC. I'm sure it also has something like "incbin". Sometimes portability is just having a version for every supported possibility.
Carpe diem!
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: BOOTBOOT Font Linking problem

Post by bzt »

nullplan wrote:

Code: Select all

.section ".rodata",  "a", @progbits
.global font_start
.type font_start, @object
font_start:
.incbin "font.psf"
.global font_end
.type font_end, @object
font_end:
That should work for all ELF architectures.
I seriously doubt that the FreePascal or the Rust compiler for example can do anything with this code... (Pascal uses a different inline asm syntax, and Rust for example doesn't really support global labels in inline asm).
As I've said, it was an important goal to only use the main language with its compiler, but nothing else, which means no additional tools nor assemblers. This is why Assembly is out of question for the mykernel examples (in a real kernel project, where an assembler is a must have sure, you can use "incbin" too, or "file" or "bininc" or whatever syntax your chosen assembler supports).
nullplan wrote:For PE the section name would be ".rdata", which you can abstract with a preprocessor directive, as necessary.
Unlike C, Pascal and Ada, for example the Go compiler doesn't have a preprocessor at all. (And it can't import variables from another object file, just functions with a very overcomplicated way, btw. so even if you compile this with an assembler, there's no way to access the included data from Go. FYI, ld and objconv doesn't work either with Go, I had to use the bin2h way, furthermore, Go can't store initialized static byte arrays, so I had to use a string constant... Ugly and dirty workaround. You have probably figured that out, my dislike towards Go is because I had the most issues and trouble with that port. That's a shitty, not a well-tough language which required the most workarounds by far. Oh, and the official compiler doesn't work for bare metal, not even their own tutorials compile with that, you _must_ use the GNU compiler, gccgo.)
nullplan wrote:Since the file contains no architecture specific code, any version of GNU as should be able to compile this, no matter the target architecture, and probably also some other assemblers. The C interface is "extern const char font_start[], font_end[]".
ld does exactly the same, but needs no additional assembler to achieve that goal. First, doesn't matter what language you use, you'll need the linker anyway, you can't leave that out; second, it creates the object no matter the target architecture. So, why not use the tool that we already have?
nullplan wrote:And if you need to support MSVC
I don't think MSVC can compile Pascal, Ada or Go for example. The GNU compiler can. (That put aside, I do support MSVC C/C++ for kernels, the bootboot.h is written carefully in a way to support the messed up MSVC pragma syntax too, but I don't provide a mykernel example for that compiler.)

Cheers,
bzt
Octocontrabass
Member
Member
Posts: 5568
Joined: Mon Mar 25, 2013 7:01 pm

Re: BOOTBOOT Font Linking problem

Post by Octocontrabass »

bzt wrote:FreePascal
The FreePascal compiler uses gas as its assembler, which means it's not an additional tool.
bzt wrote:inline asm
I don't think anyone is suggesting using inline assembly.
bzt wrote:ld does exactly the same, but needs no additional assembler to achieve that goal. First, doesn't matter what language you use, you'll need the linker anyway, you can't leave that out; second, it creates the object no matter the target architecture. So, why not use the tool that we already have?
But ld and gas are both part of binutils. If you have one, you have both.
User avatar
bzt
Member
Member
Posts: 1584
Joined: Thu Oct 13, 2016 4:55 pm
Contact:

Re: BOOTBOOT Font Linking problem

Post by bzt »

Octocontrabass wrote:I don't think anyone is suggesting using inline assembly.
Yes, because you've failed to understand the main goal. I repeat it for the third time: only one kind of language source files per directory allowed. In pas: only pascal sources. In ada: only ada sources. In cpp: only C++ sources. Hence only inline asm can be considered at best. Having a separate Assembly file is out of question because it goes against the main goal. And yes, I've failed to fulfill this goal with Go (but I could mitigate it to a common Assembly file for all platforms), and yes, your project might have a different goal than my mykernel examples.
Octocontrabass wrote:But ld and gas are both part of binutils. If you have one, you have both.
I've never said binutils is a dependency. I only said "A linker". That could be Gold ld or LLVM lld too, those are command line compatible with GNU ld (mostly). With the C and C++ examples, you should be able to use ANY compiler, and ANY linker, there's absolutely nothing GNU specific in the code or in the linker scripts (and bootboot.h is written with ifdef guards to support MSVC too). The failure with Go and depending on gccgo is no reason to limit the other languages to GNU too. (Admittedly I only provide Makefiles for that, simply because I don't have the capacity to support all possible compilers. But contributions are welcome any time ;-) If you have a working vcproj for mykernel, open a PR, and I can promise I'll add it.)

Cheers,
bzt
Ethin
Member
Member
Posts: 625
Joined: Sun Jun 23, 2019 5:36 pm
Location: North Dakota, United States

Re: BOOTBOOT Font Linking problem

Post by Ethin »

There's no need to use assembly at all for including binary files in Rust. That's actually a bit overkill and you rarely ever should have to do that. The bootloader I use doesn't even do that for the kernel -- the kernel and bootloader are linked together though. To include binary data in a rust project, use include_bytes!, like so:

Code: Select all

let font_data = include_bytes!("font.bin");
Quite a useful macro, that is.
Post Reply