Using linux syscall with older glibc - glibc

I want to use the timerfd in a embedded device solution which runs a 2.6.39 kernel, but the cross compiler uses a too old glibc (2.5). Timerfd exists since 2.6.25, but only since glibc 2.8
When i try to use the header file from a newer glibc, the compiler complains about not finding the extern timerfd_create (undefined reference to 'timerfd_create'), but I can't find the implementation anywhere in the glibc.
My question now is, how can I use the timerfd, regardless of the old glibc version? Do I have to invoke the syscall manually? If yes, how do I do so?

I can't find the implementation anywhere in the glibc.
Here is trick to finding it: with libc6-dbg installed:
gdb -q /lib/x86_64-linux-gnu/libc.so.6
(gdb) list timerfd_create
61 ../sysdeps/unix/syscall-template.S: No such file or directory.
This tells you that the implementation is simply to pass arguments directly to the kernel via system call.
Your implementation can then be:
#include <unistd.h>
#include <syscall.h>
#ifndef __NR_timerfd_create
#define __NR_timerfd_create 283
int timerfd_create(int clockid, int flags)
{
return syscall(__NR_timerfd_create, clockid, flags);
}
#endif

Related

GNU toolchain (newlib): compatibility between toolchain versions (undefined symbol __ctype_ptr__)

Having here a project that is using some external GNU-toolchain built libraries (provided externally, without source-code). I'm compiling an application for embedded systems (FreeRTOS specifically), so I use newlib.
I initially tried using this toolchain https://releases.linaro.org/components/toolchain/binaries/7.4-2019.02/aarch64-elf/
but that failed because of (among others) these linker errors:
undefined reference to `__ctype_ptr__'
It seems that this symbol should be defined by libc. Going into the newlib sysroot, specifically in this case the sysroot-newlib-linaro-2019.02-aarch64-elf\usr\lib directory, tried to find __ctype_ptr__ in libc.a:
aarch64-elf-nm -C --defined-only -g libc.a | grep __ctype_ptr__
No output, so this libc indeed does not define __ctype_ptr__.
Continuing by taking a look into the library that needs the symbol, a notepad++ edit revealed this among the mangled text:
/opt/gcc-linaro-5.4.1-2017.05-x86_64_aarch64-elf/aarch64-elf/libc/usr/include/machine
Which means this library was built using the 5.4.1 aarch64-elf toolchain version and I was trying to use version 7.4 since I need newer C++ standard support.
Downloaded the 5.4.1 version as well (sysroot only): https://releases.linaro.org/components/toolchain/binaries/5.4-2017.05/aarch64-elf/
Again, going into the 5.4.1 sysroot-newlib-linaro-2017.05-aarch64-elf\usr\lib directory this time:
aarch64-elf-nm -C --defined-only -g libc.a | grep __ctype_ptr__
finally reveals:
0000000000000000 D __ctype_ptr__
which means that indeed the 5.4.1 newlib libc exports this symbol.
Questions:
Why this incompatibility between the 2 versions? What category do these kind of changes belong to? Where can I find more detailed information about changes like these and the reasons they are there?
Am I forced to use the old version because those libraries were built with it? Is there no way to use the newer version instead? How are these situations usually handled?
_ctype_ptr_ is simply a pointer to _ctype_ which is a 128 byte table
containing a bitset used by the ctype.h functions like isalpha.
The functions will take a character as a parameter, and will use the
character as an index into the _ctype_ array.
A mask is applied to the read value, and if non-zero the function returns "true"
You can worst case define your own
extern const char _ctype_[];
const char* __ctype_ptr__ = _ctype_;
If _ctype_ is reported undefined by the linker,
you may have to define it in the linker
ctype = _ctype_;
and in the source code.
extern const char ctype[];
const char* __ctype_ptr__ = ctype;

gcc-4.8.2 doesn't link pthread

all.
Compiling simple stuff using the gcc toolchain for several years, today I ran against a curious phenomenon.
I installed Kubuntu 14.04 to a common desktop i686 machine with gcc 4.8.2 in it. But then, trying to build some well coded stuff pulled out from my local repository, I ran against tons of 'undefined reference to' messages. The code compiles, links und runs well under Ubuntu 11.04 / gcc 4.5.2.
I checked the linking process (by -Wl,--verbose to gcc), think it works. It finds all libraries I specify in the link command. An objdump -t myLib.so brings exactly the symbols I'd expect - but the linker doesn't see them.
Checking the pthread library also brings according symbols, except they are suffixed with some #GLIBC... stuff. Didn't check linker/loader tricks so far.
A sample like
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
static void *fooo (void *xxx) {
char *txt = (char*)xxx;
printf("My job is to print this :'%s'. Bye now!\n", txt);
return 0;
}
int main (int argc, char *argv[]) {
pthread_t thd;
pthread_create(&thd, NULL, fooo, "A POSIX thread");
sleep(1);
return 0;
}
runs very well on the old system just saying
gcc -l pthread fooo.c && ./a.out
but breaks at the linking step with 4.8.2.
Any idea would be very welcome.
.M
Thanks to sfrehse, JoachimPileborg et al!
Indeed, success depends on argument order. I knew this fact for static linking, but it is new in processing of shared objects with gcc.
Does someone know what the background of this improvement is? It breaks innumerable build processes, and I guess thousands of tomatoes are being made ready against gcc.gnu.org .....
.M

Unknown type name ‘off64_t’

I have a problem using Apache Portable Runtime on Ubuntu with GCC 4.8.1
The problem is that the off64_t from <sys/types.h> is not available when compiling with gcc. (When compiling with g++ everything work fine)
Does anybody know which compiler switch to use to enable off64_t? (I know that defining _LARGEFILE_SOURCE _LARGEFILE64_SOURCE avoids the problem, but wondering if this is the right way)
To reproduce the error one can simply try to compile the following code:
#include <sys/types.h>
off64_t a_variable;
off64_t is not a language defined type. No compiler switch will make it available.
It is defined in sys/types.h, but (on a 32 bit system) only if
_LARGEFILE64_SOURCE is defined
Which will make the 64 bit interfaces available (off64_t, lseek64(), etc...).
The 32 bit interfaces will still be available by their original names.
_FILE_OFFSET_BITS is defined as '64'
Which will make the names of the (otherwise 32 bit) functions and data types refer to their 64 bit counterparts.
off_t will be off64_t, lseek() will use lseek64(), and so on...
The 32 bit interface is no longer available.
Make sure that if you define these macros anywhere in your program, you define them at the beginning of all your source files. You don't want ODR violations to be biting you in the ass.
Note, this is for a 32 bit system, where off_t is normally a 32 bit value.
On a 64 bit system, the interface is already 64 bits wide, you don't need to use these macros to get the large file support.
off_t is a 64 bit type, lseek() expects a 64 bit offset, and so on.
Additionally, the types and functions with 64 in their name aren't defined, there's no point.
See http://linux.die.net/man/7/feature_test_macros
and http://en.wikipedia.org/wiki/Large_file_support
You also may be interested to know that when using g++, _GNU_SOURCE is automatically defined, which (with the gnu c runtime library) leads to _LARGEFILE64_SOURCE being defiend. That is why compiling your test program with g++ makes off64_t visible. I assume APR uses the same logic in making _LARGEFILE64_SOURCE defined.
Redefine off64_t to __off64_t in your compile flag. Edit your Makefile so it contains:
CFLAGS= -Doff64_t=__off64_t
then, just run $ make 1 (assuming you have 1.c in your directory)
A bit late, but still current.
I simply add -Doff64_t=_off64_t to the compiler flags.
In my environment gcc version 4.1.2, I need to define __USE_LARGEFILE64. I found this macro from /usr/include/unistd.h who defines lseek64()
#define __USE_LARGEFILE64
#include <sys/types.h>
#include <unistd.h>
You should define $C_INCLUDE_PATH to point to linux headers, something like
export C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
To install linux header, use
sudo apt-get install linux-headers-`uname -r`
P.S.
$ cat 1.c
#include <sys/types.h>
off64_t a_variable;
int main(){return 0;}
$ gcc --version
gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1
$ echo $C_INCLUDE_PATH
/usr/include/x86_64-linux-gnu
$ grep off64_t /usr/include/x86_64-linux-gnu/sys/types.h
typedef __off64_t off_t;
#if defined __USE_LARGEFILE64 && !defined __off64_t_defined
typedef __off64_t off64_t;
# define __off64_t_defined
Sorry for the lateness but I did never had to embed perl code in C programs untill today ^^
I solved the issue in Unix/Linux systems (I think it is possible to create such feature in Windows since Vista) by creating a symbolic link pointing to the CORE folder of perl version...
ln -s $(perl -MConfig -e 'print $Config{archlib}')/CORE /usr/include/perl
In your project file, source code, simply add:
#include <perl/EXTERN.h>
#include <perl/perl.h>
...and I came from long list of notes and errors related to off_t and off64_t to a clean build result ^^
Also late to the party, but the main reason for receiving this issue was installing the 64-bit version of MinGW instead of 32-bit:
https://sourceforge.net/projects/mingw/

MEX compile error: unknown type name 'char16_t'

I cannot compile any MATLAB MEX code due to the following error:
In file included from /Applications/MATLAB_R2013a.app/extern/include/mex.h:58:
In file included from /Applications/MATLAB_R2013a.app/extern/include/matrix.h:294:
/Applications/MATLAB_R2013a.app/extern/include/tmwtypes.h:819:9: error: unknown type name 'char16_t'
typedef char16_t CHAR16_T;
The only thing that has changed on my machine as far as I can remember is that Xcode was updated to version 5.1 (5B130a).
Any fix for the time being to compile MEX code in MATLAB?
[Running on OS 10.9.2 with Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)]
By default, the upgraded Clang doesn't set char16_t, which is required by MATLAB.
Quick fix
This works for C or C++ code but needs to be done on each mex command line.
>> mex -Dchar16_t=uint16_t ...
Other solutions below put this definition into the mex configuration or enable C++11.
Permanent solution
Options:
Add -std=c++11 to CXXFLAGS in your mex configuration file AND compile .cpp files instead of .c. The mex config file is mexopts.sh (pre-R2014a) or the .xml file indicated by mex -setup (R2014a+). This is what worked for OP, but the next option works too. Be sure to edit the active/installed config, not the system-wide reference. Try the next solution if you can't tell.
Use a #define or typedef to create char16_t before including mex.h (see "other workaround" below).
In some future version of MATLAB, this will have been fixed. Re-run mex -setup to have MATLAB reconfigure it for you and it works. As of R2014a, this doesn't do the trick.
As a last resort, you can always modify the MATLAB installation, hacking MATLAB's tmwtypes.h as Dennis suggests, but I strongly suggest NOT modifying the MATLAB installation.
Note: If you are using C and cannot or don't want to change to C++, follow the solution in this other answer, OR see the alternative workaround below.
The other workaround
If for some reason you are not able to enable the C++11 standard, you can use the preprocessor to define char16_t. Either put #define char16_t uint16_t before #include "mex.h", or set it with the compiler command line:
-Dchar16_t=uint16_t
Alternatively, use a typedef, again before including mex.h:
typedef uint16_t char16_t;
If these solutions don't work, try changing uint16_t to UINT16_T. Further yet, others have reported that simply including uchar.h brings in the type, but others don't have that header.
I experienced the same error, also directly after upgrading to Xcode 5.1.
The relevant lines (818-824) in the file tmwtypes.h, which causes the error, are:
#if defined(__STDC_UTF_16__) || (defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT)
typedef char16_t CHAR16_T;
#elif defined(_MSC_VER)
typedef wchar_t CHAR16_T;
#else
typedef UINT16_T CHAR16_T;
#endif
A solution is to simply change the line
typedef char16_t CHAR16_T;
into
typedef UINT16_T CHAR16_T;
A must admit that I don't know if this affects any function or behaviour of mex files but at least I'm able to compile my c files again using mex.
Please see other answers if this method doesn't work.
I upgraded my gcc/g++ compilers using homebrew to version 4.8 --> gcc-4.8 and g++-4.8.
After that I changed the following lines in the mexopts.sh file:
CXXFLAGS="-fno-common -fexceptions -arch $ARCHS -isysroot $MW_SDKROOT -mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET -std=c++11"
In my mexopts.sh, this is line 150. I only added the -std=c++11 flag which is what I guess chappjc meant.
EDIT: This is covered in the update by chappjc!
I just add my own experiment (C++ only). The
#define char16_t uint16_t
was causing some problem in the other parts of the mex file. In fact, subsequently to my mex file, char16_t was properly defined. By tracking the chain of includes, the proper type char16_t is set in a file named __config :
typedef __char16_t char16_t;
which is also the first file included from <algorithm>. So the hack consists in including algorithm before mex.h.
#include <algorithm>
#include "mex.h"
and the proper settings are performed, still in a multiplatform manner and without changing anything in the build configuration.
Include uchar.h before including mex.h...works fine. Also, the answer above (adding -std=c++11) only works for c++, not c.
#include <uchar.h>
#include "mex.h"
As part of XCode 5.1.1 char16_t is defined in __config, which is called from typeinfo.
You can add
#include <typeinfo>
before
#include "mex.h"
to have char16_t defined.
This post might help: http://www.seaandsailor.com/matlab-xcode6.html
It was easier than I thought. Just replace all 10.x with your OS X version and add -Dchar16_t=UINT16_T to CLIBS in mexopts.sh file.
It worked on OS X 10.9 Mavericks with Xcode 6 installed.

program crash after modification on gcc and gcov

Recently I'm trying to modify GCC and gcov to collect execution sequence for program. As we all know, gcc will instrument code on arcs between basic blocks to count the execution count of arc. So I instrument a function on the arc, and the function will print out the no of that arc, so I can collect program execution sequence. It works well for c program on x86 and x86_64, also for c++ program of x86. But for c++ program on x86_64, the program will crash by segment error. The compilation has no problem. The os that I use is CentOS 6.4. Version of gcc is 3.4.5. Does anybody has some advice?
sample program:
#include <iostream> using namespace std; int main(){cout<<"hello world"<<endl;}
If I compile the program in x86_64 mode. The program crash by Segment Error when comes to the cout CALL.
Ok, by another night debug on it. I found that the function emit_library_call will only generate asm code to invoke my function, but not protect the context (registers). So function call before or after the emitted code may fail due to nonuniform context. And x86_64 asm use different registers with x86. So to work well on x86 platform may be just accident. I need a function api which can emit library function call and also protect the context. Maybe I should write another emit_library_call.
Perhaps you might try a dynamic binary translation framework, e.g. DynamoRIO or Pin. These tools offer more flexibility than you need, but they would allow you do inject code at the beginning/end of each basic block. What you then want to do is save/restore the flags and registers (and potentially re-align the stack), and call out to a function. DynamoRIO has similar functionality built in, named a "clean call". I think Pin also enables this with a potentially higher-level interface.
I did same thing what you did in 3.5.0-23-generic #35~precise1-Ubuntu SMP Fri Jan 25 17:13:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
#include <iostream>
`using namespace std;
int main()
{
cout<<"hello world"<<endl;
}`
compiled above code with g++ -ftest-coverage -fprofile-arcs hello.cpp -o hello
hello.gcno file is generated.
After executing ./hello hello.gcda file generated .
So once check your gcc version .
My gcc version is gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

Resources