BOOTBOOT Font Linking problem
-
- Posts: 16
- Joined: Thu Jul 01, 2021 3:24 pm
BOOTBOOT Font Linking problem
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?
Re: BOOTBOOT Font Linking problem
What objdump say about your font file? Have you ran objcopy to turn it into an ELF?
-
- Member
- Posts: 5568
- Joined: Mon Mar 25, 2013 7:01 pm
Re: BOOTBOOT Font Linking problem
No.LyricalRain wrote:does the directory structure affect the linking with the font binary object file?
Maybe you made a mistake when you updated the paths in the makefile. Are there any other errors?LyricalRain wrote:If not, what could be the possible problem?
Re: BOOTBOOT Font Linking problem
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
Re: BOOTBOOT Font Linking problem
Yes.Octocontrabass wrote:No.LyricalRain wrote:does the directory structure affect the linking with the font binary object file?
Re: BOOTBOOT Font Linking problem
Yes, it does change the variable's name unfortunately.monarrk wrote:Yes.Octocontrabass wrote:No.LyricalRain wrote:does the directory structure affect the linking with the font binary object file?
Exactly. FYI my Makefile uses ld, not objcopy, but the same.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
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.
-
- Member
- Posts: 5568
- Joined: Mon Mar 25, 2013 7:01 pm
Re: BOOTBOOT Font Linking problem
Wouldn't it be easier (and faster) to use the incbin directive in an assembly file instead of an array in a C header?bzt wrote:bin2h.c
Re: BOOTBOOT Font Linking problem
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).Octocontrabass wrote:Wouldn't it be easier (and faster) to use the incbin directive in an assembly file instead of an array in a C header?bzt wrote:bin2h.c
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
-
- Posts: 16
- Joined: Thu Jul 01, 2021 3:24 pm
Re: BOOTBOOT Font Linking problem
Thank you for your replies! I thought the directory thing must be it but I couldn't pinpoint the error.
Re: BOOTBOOT Font Linking problem
Normally not, but in this case:bzt wrote:No, not for me. Assembly isn't portable and not all compilers support inline Assembly.
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:
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!
Re: BOOTBOOT Font Linking problem
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).nullplan wrote:That should work for all ELF architectures.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:
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).
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:For PE the section name would be ".rdata", which you can abstract with a preprocessor directive, as necessary.
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: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[]".
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.)nullplan wrote:And if you need to support MSVC
Cheers,
bzt
-
- Member
- Posts: 5568
- Joined: Mon Mar 25, 2013 7:01 pm
Re: BOOTBOOT Font Linking problem
The FreePascal compiler uses gas as its assembler, which means it's not an additional tool.bzt wrote:FreePascal
I don't think anyone is suggesting using inline assembly.bzt wrote:inline asm
But ld and gas are both part of binutils. If you have one, you have both.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?
Re: BOOTBOOT Font Linking problem
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:I don't think anyone is suggesting using inline assembly.
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.)Octocontrabass wrote:But ld and gas are both part of binutils. If you have one, you have both.
Cheers,
bzt
Re: BOOTBOOT Font Linking problem
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:
Quite a useful macro, that is.
Code: Select all
let font_data = include_bytes!("font.bin");