ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Hi everybody.
This might seem a strange question, but I have 2 lines of code that I expect to do the exact same thing. The trouble is, only one of them works.
This is running on Linux x86_64, and I tried with both Musl and glibc, as well as my own assembly routine. I think the Linux x86_64 calling convention should pass the arguments like this, but it doesn't work. I looked at both musl source and glibc source, and both seem to say I'm not doing anything wrong.
The mmap2 syscall seems to not be available on x86_64 machines, so I do not think I should be using that instead. But I am doing something wrong and I am just not smart enough to spot it.
The mmap2 syscall seems to not be available on x86_64 machines, so I do not think I should be using that instead.
Did you try it? The manpage says different:
Quote:
Originally Posted by man 2 mmap
Originally, this function invoked a system call of the same name. Since kernel 2.4, that system call has been superseded by mmap2(2), and nowadays the glibc mmap() wrapper function invokes mmap2(2) with a suitably adjusted value for offset.
/tmp/cc4HPBOs.o: In function `main':
fblog.c:(.text+0x159): undefined reference to `mmap2'
collect2: error: ld returned 1 exit status
SYS_mmap2 syscall:
Code:
./fblog.c:44:29: error: ‘SYS_mmap2’ undeclared (first use in this function)
fbp = (uint8_t *)__syscall(SYS_mmap2, 0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
Also, I can see in /usr/include/bits/syscall.h that SYS_mmap2 is defined only if WORDSIZE is 32.
Seems like the manpage is correct for 32 bit machines only.
I tried a few more things and discovered something interesting. The code works fine with the musl c library. Do you think it's possible that I have located a bug in glibc?
I can't imagine how that could be since syscall() gets used internally in glibc for almost every function, how could that function have a bug like this?
But if there is no bug and my code is the problem, why does it work fine with musl libc?
Be careful passing NULL pointers as bare 0's. NULL is often #defined as (void *)0 and it is 64 bits wide on your platform whereas a bare 0 is a 32-bit integer. When passing parameters to variadic functions, as there is no strict function definition, the compiler's only cue to argument type and size is what you give it.
Your syscall() invocation passes the first argument to mmap() as a 32-bit integer, not a pointer as you expected. The final argument to mmap() probably should be cast to off_t in case it's 64-bit, too.
Be careful passing NULL pointers as bare 0's. NULL is often #defined as (void *)0 and it is 64 bits wide on your platform whereas a bare 0 is a 32-bit integer. When passing parameters to variadic functions, as there is no strict function definition, the compiler's only cue to argument type and size is what you give it.
Your syscall() invocation passes the first argument to mmap() as a 32-bit integer, not a pointer as you expected. The final argument to mmap() probably should be cast to off_t in case it's 64-bit, too.
Ahh, thats wonderful. totally my mistake, I made the assumption that ints and pointers and off_ts should be the same size. Silly me. I have it working now with glibc at least. Now I just have to debug my assembly code and everything will be perfect.
Well, on CPU-level, function-parameters are always word-sized (either in registers or stack-levels), so in 64-bit environment, passing a 64-bit value to a 32-bit parameter should be okay; on the other hand, a 32-bit value cannot be passed to a 64-bit parameter without type-cast, because the upper 32-bit might contain random garbage (this is the case on x86_64 platform).
Edit:
Correction:
old: function-parameters are always word-sized
new: function-parameters are always word-sized, or the multiple of that, eg: int64_t in 32-bit environment takes two stack-levels
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.