Building coreboot: undefined reference __udivmoddi4 - gcc

In building coreboot I got error regarding during linking:
coreboot/src/console/vtxprintf.c:102: undefined reference to '__udivmoddi4'.
Where can I find the library containing this function?
I'm building coreboot for x86_64 (Lenovo x230) using gcc (8.1.1 20180531).
Coreboot - git hash: f59a052ee8dae6f1378514cb622d229e652ad2f6

__udivmoddi4 is a function in libgcc which is used to implement a combined unsigned division/modulo operation for what GCC calls DI mode (doubled-up integers, 64-bit on i686). It is used for operations like this one:
unsigned long long
div (unsigned long long a, unsigned long long b, unsigned long long *p)
{
*p = a % b;
return a / b;
}
The use of __udivmoddi4 on i386 is a new optimization in GCC 7, related to this patch. Previous versions emitted separate calls to __umoddi3 and __udivdi3, basically doing the same work twice.
Normally, all these functions are provided by libgcc, but Coreboot does not link against the standard libraries. It supplies its own implementations of these functions in payloads/libpayload/libc/64bit_div.c, but __udivmoddi4 has yet to be added there.
Either you implement the function yourself (easiest way would be to call __umoddi3 and __udivdi3 from it), or you use GCC 6 to compile Coreboot for the time being. Lowering the optimization level just for the printf implementation might constitute a workaround.

I faced the same problem today, and found out that Coreboot is made to be built using the i386 toolchain, not the x86_64. See https://doc.coreboot.org/tutorial/part1.html:
Note that the i386 toolchain is currently used for all x86 platforms, including x86_64.
After cloning coreboot, one should run make crossgcc-i386 CPUS=$(nproc) to build a compatible toolchain.
Here is the mailing list that gave me the hint:
https://mail.coreboot.org/pipermail/coreboot/2018-August/087195.html

Related

Creating and linking static rust library and link to c

I tried to create a rust library that is callable by a c program, so far i managed to create a dynamic library and call it (library created using rustc --crate-type=cdylib src/lib.rs -o libCustomlib.so, linked using gcc main.o -lCustomlib).
When i now take the same code but compile it as a static library (rustc --crate-type=staticlib src/lib.rs -o libCustomlib.a) gcc throws errors when linking (using gcc main.o -L. -l:libCustomlib.a)
the errors are all undefined references to various functions
first few lines:
/usr/bin/ld: ./libCustomlib.a(std-b1b61f01951b016b.std.5rqysbiy-cgu.2.rcgu.o): in function `std::sys::unix::mutex::Mutex::init':
/usr/src/rustc-1.43.0//src/libstd/sys/unix/mutex.rs:46: undefined reference to `pthread_mutexattr_init'
/usr/bin/ld: /usr/src/rustc-1.43.0//src/libstd/sys/unix/mutex.rs:48: undefined reference to `pthread_mutexattr_settype'
/usr/bin/ld: /usr/src/rustc-1.43.0//src/libstd/sys/unix/mutex.rs:52: undefined reference to `pthread_mutexattr_destroy'
full error is over 100 lines long but the lines are all of this form
the lib.rs currently only has one test helloWorld function:
#[no_mangle]
pub extern "C" fn fn_test() {
println!("Hello, world!");
}
with the header file included in the caller part being:
extern void fn_test();
The question is, is my error at creating the static library or at linking it? Or lies the problem somewhere else and it should not work with static libraries? Should i just use the dynamic approach (which i would like to avoid since static ones feel more like using multiple languages in one exe since you don't have to distribute the library)?
(disclaimer: for everyone asking why i would do something like that without a good reason: it's a fun project, the entire program should be as overcomplicated as possible and that's the reason why i want to use different languages)
On Linux, std dynamically links to pthreads and libdl. You need to link these in as well to create the executable:
gcc main.o libCustomlib.a -lpthread -ldl
The result is a binary that links dynamically to a handful of fundamental libraries, but statically to Customlib.
If you want a purely statically linked binary, you will probably need to use no_std and enable only the specific features of core that do not depend on dynamically linked system libraries. (Certain libraries cannot be statically linked on Linux; read Statically linking system libraries, libc, pthreads, to aid in debugging) Just for a toy program like hello, world you may get away with simply passing -static to gcc, but for anything robust it's better to dynamically link these fundamental libraries.

gcc vector extensions don't work as stated in docs

As per Using vector instructions through built-in functions, this program should compile:
int main(){
double v_sse __attribute__ ((vector_size (16)));
/*
* Should work: "For the convenience in C it is allowed to use a binary vector operation where one operand is a scalar."
*/
v_sse=v_sse+3.4;
/*
* Should work: "Vectors can be subscripted as if the vector were an array with the same number of elements and base type."
*/
double result=v_sse[0];
}
Instead I get errors at both operations, complaining about invalid operand/types.
I compile on a x86-64 system, so -msse2 is implicit, and my compiler is 4.6.3 (tested also with 4.7.0, it doesn't work). Where's the catch?
The documentation at http://gcc.gnu.org/onlinedocs/gcc/ refers to current development.
Look at http://gcc.gnu.org/onlinedocs/gcc-X.Y.Z/ to find the documentation for the version you're using (see the index at http://gcc.gnu.org/onlinedocs/ for links to the docs for the most recent point release of each series).
In this case:
the binary operator functionality is not documented for 4.6.3 - because it was introduced as a new feature in 4.7: see the 4.7 release notes;
the subscript feature is present in 4.6.3; and
both features are specifically documented as working "in C"
...which explains what you're seeing.
Both of these do work with 4.7.0 when compiling as C -- but not when compiling as C++.

GCC atomic built-ins: Is there a list showing which are supported on which platform?

Is there a site listing the various platforms and their support for GCC's atomic built-ins, for the various GCC versions?
EDIT:
To be more clear:
GCC adds _sync... as intrinsics on platforms it contains support for. On all other platforms it keeps those as normal functions declarations but does not supply an implementation. This must be done by some framework.
So the question is: For which platforms does GCC supply which intrinsics without need to add a function implementation?
I'm not aware if there's such a list, however http://gcc.gnu.org/projects/cxx0x.html says atomics are supported since GCC 4.4.
GCC libstdc++ implements <atomic> on top of the builtin functions `__sync_fetch_and_add' and friends ( http://gcc.gnu.org/onlinedocs/gcc-4.6.1/gcc/Atomic-Builtins.html ).
These functions are expanded either using machine specific expanders in the machine description of the target (usually in a file named `sync.md') or, lacking such expanders, using a CAS loop. If the presense of `sync.md' file is any indication for a proper atomics support, then you can count in MIPS, i386, ARM, BlackFin, Alpha, PowerPC, IA64 and Sparc.
[Though this is an old question, I thought I should update and complete the answer]
I am not aware of a per-architecture-version and per-gcc-version table, describing supported built-ins.
The __sync built-in functions of gcc exist since version 4.1 (see, e.g., gcc 4.1.2 manual. As stated there:
Not all operations are supported by all target processors. If a particular operation cannot be implemented on the target processor, a warning will be generated and a call an external function will be generated. The external function will carry the same name as the builtin, with an additional suffix `_n' where n is the size of the data type.
So, when there is not an implementation for a specific architecture, a compilation warning will appear and, I guess, a link-time error, unless you provide the required function with the appropriate name.
After gcc 4.7 there are also __atomic built-ins and __sync built-ins are deprecated.
For example, see how Fedora uses gcc __sync and __atomic here

Getting GCC to compile without inserting call to memcpy

I'm currently using GCC 4.5.3, compiled for PowerPC 440, and am compiling some code that doesn't require libc. I don't have any direct calls to memcpy(), but the compiler seems to be inserting one during the build.
There are linker options like -nostdlib, -nostartfiles, -nodefaultlibs but I'm unable to use them as I'm not doing the linking phase. I'm only compiling. With something like this:
$ powerpc-440-eabi-gcc -O2 -g -c -o output.o input.c
If I check the output.o with nm, I see a reference to memcpy:
$ powerpc-440-eabi-nm output.o | grep memcpy
U memcpy
$
The GCC man page makes it clear how to remove calls to memcpy and other libc calls with the linker, but I don't want the compiler to insert them in the first place, as I'm using a completely different linker (not GNU's ld, and it doesn't know about libc).
Thanks for any help you can provide.
There is no need to -fno-builtins or -ffreestanding as they will unnecessarily disable many important optimizations
This is actually "optimized" by gcc's tree-loop-distribute-patterns, so to disable the unwanted behavior while keeping the useful builtin capabilities, you can just use:
-fno-tree-loop-distribute-patterns
Musl-libc uses this flag for its build and has the following note in their configure script (I looked through the source and didn't find any macros, so this should be enough)
# Check for options that may be needed to prevent the compiler from
# generating self-referential versions of memcpy,, memmove, memcmp,
# and memset. Really, we should add a check to determine if this
# option is sufficient, and if not, add a macro to cripple these
# functions with volatile...
# tryflag CFLAGS_MEMOPS -fno-tree-loop-distribute-patterns
You can also add this as an attribute to individual functions in gcc using its optimize attribute, so that other functions can benefit from calling mem*()
__attribute__((optimize("no-tree-loop-distribute-patterns")))
size_t strlen(const char *s){ //without attribute, gcc compiles to jmp strlen
size_t i = -1ull;
do { ++i; } while (s[i]);
return i;
}
Alternatively, (at least for now) you may add a confounding null asm statement into your loop to thwart the pattern recognition.
size_t strlen(const char *s){
size_t i = -1ull;
do {
++i;
asm("");
} while (s[i]) ;
return i;
}
Gcc emits call to memcpy in some circumstance, for example if you are copying a structure.
There is no way to change GCC behaviour but you can try to avoid this by modifying your code to avoid such copy. Best bet is to look at the assembly to figure out why gcc emitted the memcpy and try to work around it. This is going to be annoying though, since you basically need to understand how gcc works.
Extract from http://gcc.gnu.org/onlinedocs/gcc/Standards.html:
Most of the compiler support routines used by GCC are present in libgcc, but there are a few exceptions. GCC requires the freestanding environment provide memcpy, memmove, memset and memcmp. Finally, if __builtin_trap is used, and the target does not implement the trap pattern, then GCC will emit a call to abort.
You need to disable a that optimization with -fno-builtin. I had this problem once when trying to compile memcpy for a C library. It called itself. Oops!
You can also make your binary a "freestanding" one:
The ISO C standard defines (in clause 4) two classes of conforming implementation. A conforming hosted implementation supports the whole standard [...]; a conforming freestanding implementation is only required to provide certain library facilities: those in , , , and ; since AMD1, also those in ; and in C99, also those in and . [...].
The standard also defines two environments for programs, a freestanding environment, required of all implementations and which may not have library facilities beyond those required of freestanding implementations, where the handling of program startup and termination are implementation-defined, and a hosted environment, which is not required, in which all the library facilities are provided and startup is through a function int main (void) or int main (int, char *[]).
An OS kernel would be a freestanding environment; a program using the facilities of an operating system would normally be in a hosted implementation.
(paragraph added by me)
More here. And the corresponding gcc option/s (keywords -ffreestanding or -fno-builtin) can be found here.
This is quite an old question, but I've hit the same issue, and none of the solutions here worked.
So I defined this function:
static __attribute__((always_inline)) inline void* imemcpy (void *dest, const void *src, size_t len) {
char *d = dest;
const char *s = src;
while (len--)
*d++ = *s++;
return dest;
}
And then used it instead of memcpy. This has solved the inlining issue for me permanently. Not very useful if you are compiling some sort of library though.

Boost.asio compilation problem: undefined reference to `__sync_add_and_fetch_8

Hey guys,
This could be a noob question, but I really can't find any useful solution through Google.
I'm testing a hello world with boost.asio, the program is quite simple:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(5));
t.wait();
std::cout << "Hello, world!\n";
return 0;
}
I passed the compilation and run well on my Intel Pentium PC (Ubuntu 10.10, gcc 4.4.5, Boost 1.46.0). The command line I used was
g++ -o a a.cpp -I /Boost-Include-Path/ -L /Boost-lib-Path/ -lboost_system
But when I compile the same code on another machine(which is a big one, I'll explain it later), it can't pass the compilation and gives such errors:
/tmp/ccOZxZBX.o: In function boost::asio::detail::gcc_sync_fenced_block::gcc_sync_fenced_block()': a.cpp:(.text._ZN5boost4asio6detail21gcc_sync_fenced_blockC1Ev[boost::asio::detail::gcc_sync_fenced_block::gcc_sync_fenced_block()]+0x4c): undefined reference to__sync_lock_test_and_set_4' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator++()': a.cpp:(.text._ZN5boost6detail12atomic_countppEv[boost::detail::atomic_count::operator++()]+0x30): undefined reference to__sync_add_and_fetch_8' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator--()': a.cpp:(.text._ZN5boost6detail12atomic_countmmEv[boost::detail::atomic_count::operator--()]+0x30): undefined reference to__sync_add_and_fetch_8' /tmp/ccOZxZBX.o: In function boost::detail::atomic_count::operator long() const': a.cpp:(.text._ZNK5boost6detail12atomic_countcvlEv[boost::detail::atomic_count::operator long() const]+0x30): undefined reference to__sync_fetch_and_add_8'
The machine I used was a SiCortex SC5832,which use MIPS64 instruction set processors, OS is changed CentoOS. Gcc 4.2.3, Boost1.46.0. Is it possible that there are problems about the compatibility of the MIPS? I added -mips64 option, but it still give the same errors.
I know this environment could not be very usual, but I think some people who are using similar big machines may face the same problem.
Any help would be appreciated. By the way, I don't have sudo permission.
Thanks,
Tony
This function is a GCC built-in function, and it was introduced around GCC 4.2 (iirc) see documentation.
According to the documentation it's not available on all target processors.
If you look at boost/smart_ptr/detail/atomic_count.hpp it looks like it would fall into the #elif defined(BOOST_SP_HAS_SYNC) block. i.e. boost/smart_ptr/detail/atomic_count_sync.hpp.
Support for this is determined in boost/smart_ptr/detail/sp_has_sync.hpp. This header essentially assumes that GCC supports this on all platforms except for a few exceptions. You might want to insert MIPS as another exception here and submit a patch to boost.
You'll also see that one workaround is to define BOOST_AC_USE_PTHREADS. This will use a mutex around the atomic count, which probably is significantly less efficient, but at least it will work until you can figure out what atomic operations are supported on MIPS64.

Resources