Page 1 of 1

[Solved] Rust string comparision fail

Posted: Thu Mar 11, 2021 2:32 pm
by pvc
I can't help but wonder why this

Code: Select all

println!("{:?}", "abc" == "abc");
prints

Code: Select all

false
I tried to use BTreeMap<&str, ...>, but it completely failed to match anything. I even tried the example from https://doc.rust-lang.org/std/collectio ... eeMap.html. But it failed to display the review of 'Office Space'. When I try to compare strings this way in normal program, everything works as supposed. But in #![no_std] environment, it just fails horribly.

Re: Rust string comparision fail

Posted: Thu Mar 11, 2021 8:52 pm
by Ethin
Could you put your actual code here? Instead of a single line? I can get string comparisons to work fine in my OS.

Re: Rust string comparision fail

Posted: Fri Mar 12, 2021 3:14 am
by iansjack
[quote="pvc"]I can't help but wonder why this

Code: Select all

println!("{:?}", "abc" == "abc");
prints

Code: Select all

false
It prints

Code: Select all

true
for me.

More to the point - why would you ever want to do a comparison of two constants like this?

Re: Rust string comparision fail

Posted: Fri Mar 12, 2021 3:38 am
by pvc
Found it. It turns out that my memcmp implementation had a bug. I absolutely forgot that there are some small bits of assembly code I had to provide at the very beginnning. I've managed to somehow copy the wrong body for my memcmp subroutine from my earlier project.

@iansjack To show that something that should definitely work, doesn't.

Re: [Solved] Rust string comparision fail

Posted: Fri Mar 12, 2021 9:17 am
by Ethin
I'm not sure how your doing things, but you should not need to write implementations of memcmp, memmove or anything else like that. The Rust core library already defines these and the compiler should be automatically generating calls to them. Do your best not to reimplement the wheel; you will find that the majority of low-level functions (memcmp, memmove and such) are things you just don't need to do in Rust, which is pretty nice. You need to do things like asm functions and such (hlt, outb, etc.), but you don't need to do things like population count or memory comparison or movement functions. (Generally, any functions that you'd need to define in libgcc can be safely omitted because they're most likely already defined in libcore, or a variant of them is. Use libcore as much as possible. (Yes, its possible to omit libcore, but I have no idea why you'd ever want to.))

Re: [Solved] Rust string comparision fail

Posted: Fri Mar 12, 2021 9:45 am
by pvc
Ethin wrote: I'm not sure how your doing things, but you should not need to write implementations of memcmp, memmove or anything else like that. The Rust core library already defines these and the compiler should be automatically generating calls to them.
It wouldn't link without 'memcpy', 'memcmp' or 'memset'. These have to be provided. Even 'core' crate documentation mentions it. It may be that if I used 'cargo' to somehow build my kernel, these could be provided by LLVM but I am doing this with Makefiles. First, I compile my kernel as static (.a) library and then link it with my multiboot startup code and few extra object files.

Re: [Solved] Rust string comparision fail

Posted: Fri Mar 12, 2021 12:13 pm
by Ethin
Yeah, your not doing things properly. Cargo should be the sole tool you use to generate binaries; you shouldn't need makefiles (that's what Cargo is for). Its very possible to write a 32-bit kernel that uses multiboot without makefiles. To do so, you need a target definition file; this looks something like:

Code: Select all

{
"llvm-target": "x86_64-kernel-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"panic-strategy": "abort",
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float"
}
Another target definition for a custom pure rust bootloader looks like this:

Code: Select all

{
    "llvm-target": "x86_64-unknown-none-gnu",
    "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
    "linker-flavor": "ld.lld",
    "linker": "rust-lld",
    "pre-link-args": {
        "ld.lld": [
	    "--script=linker.ld"
	]
    },
    "target-endian": "little",
    "target-pointer-width": "64",
    "target-c-int-width": "32",
    "arch": "x86_64",
    "os": "none",
    "features": "-mmx,-sse,+soft-float",
    "disable-redzone": true,
    "panic-strategy": "abort",
    "executables": true,
	"relocation_model": "static"
}
Information on custom target definitions can be found over here and some extra info is over here.
Then, you need to create a .cargo directory with a config.toml file inside that looks something like:

Code: Select all

[unstable]
build-std = ["core", "compiler_builtins", "alloc"]

[build]
# Replace this target string with your custom JSON file
target = "x86_64-kernel-none.json"
Then you can include custom asm to prepare your kernel for protected mode and all that jaz. You include that in your main.rs file with the global_asm! macro. The setup might seem a bit convoluted but once you get it working you (typically) never have to touch it again.
Edit: also, you *need* to do this on nightly. Beta or stable channels won't let you do this stuff.

Re: [Solved] Rust string comparision fail

Posted: Sat Mar 13, 2021 2:59 am
by pvc
@Ethin
I was able to cobble up something that uses cargo only. Now I struggle with multiple targets, which in my case are arch×mach permutations. I am able to build for multiple targets, but there are still 2 places I need to change to do so. I need to automate my build.rs (it's responsible for compiling .s files) a little bit better. Otherwise, it works.

EDIT: Multiple targets work now.

Re: [Solved] Rust string comparision fail

Posted: Sat Mar 13, 2021 12:10 pm
by Ethin
Congratulations. Enjoy OS Dev on Rust! :-)