Cell SPU error in C - c

When I compile a SPU program, I get the following compilation error:
(.text+0x28): relocation truncated to fit: SPU_ADDR18 against symbol `_end' defined in *ABS* section in spu
What does it mean?
The error comes only after I have included at the very beginning:
#define CACHE_NAME MY_CACHE
#define CACHED_TYPE double
#define CACHELINE_LOG2SIZE 11
#define CACHE_LOG2NWAY 2
#define CACHE_LOG2NSETS 4
#include <cache-api.h>

The error means:
an object references the symbol '_end' using the relocation mode SPU_ADDR18
the actual adress of the symbol '_end' is too big for the mode of reference used.
_end is a symbol traditionally defined at the end of code and data segment. So most probably, you have more code and static data than the SPU support. (SPU support 256Kb that is 18 bits of address, so I guess that the relocation kind SPU_ADDR18 is the most flexible one).

The error means that the elf executable that you're building doesn't fit into SPU memory; probably because the cache-api.h header defines some static/global variables. Notice that your executable can't use more than 251Kb of memory (part of which will likely be part of the job kernel, code and data).

Related

C compiling: relocation truncated to fit R_X86_64_PC32 against symbol

/* my program
author/date: me/now
*/
# include <stdio.h>
# define XX 1000
# define YY 20000 /* value of 1000 is ok */
# define ZZ 6000
/* global variable declaration */
int some_variable_this;
int some_variable_that;
double data[XX][YY][ZZ];
static void some_procedure_this ( void )
{
}
static void some_procedure_that ( void )
{
}
int main ( int argc, char *argv[] )
{
}
writing a quick C program to reformat some data.
when compiling via gcc myprogram.c if I make the global data array too large I get the compiler error:
relocation truncated to fit R_X86_64_PC32 against symbol 'some_variable_this'
relocation truncated to fit R_X86_64_PC32 against symbol 'some_variable_that'
My goal is to do a quick c code to reformat some data.
What does this R_X86_64_PC32 mean?
Is there a compiler flag I can used to get around this?
Is there a better way to code this, in C, while still maintaining quickness of writing the code and simplicity for human readability?
this on gcc 4.3.4 in linux if it matters.
What does this R_X86_64_PC32 mean?
It is an ELF relocation type used in ELF for x86_64. This particular type expresses that the location of the referenced data is computed based on a 32-bit offset from the an address related to the program counter. I interpret the diagnostics to indicate that the needed offsets are too large to fit in the provided 32 bits, which means that the compiler generated code that, in practice, the linker wasn't able to link correctly.
Is there a compiler flag I can used to get around this?
Maybe. The basic problem is that you've defined an object that is larger than the authors of your compiler imagined (at the time) that anyone would be able to accommodate. You're going beyond its design limits.
There may be options that would mitigate this effect. In particular, you could try twiddling the -fPIC and / or -fPIE options, and there may be others.
Is there a better way to code this, in C, while still maintaining quickness of writing the code and simplicity for human readability?
It's not a C problem per se, it's an implementation problem. Yet GCC is not wrong or faulty here as far as the language standard is concerned -- the standard does not obligate implementations to accept every possible program that is technically valid.
With that said, you could also try moving the declarations of some_variable_this and some_variable_that after the declaration of data. Conceivably, it might also help to declare those variables static, or to move them (or data) to a separate shared library.

what is the role of .LANCHOR0 in detecting multiple definitions error?

I got a multiple definitions error and I fixed it by putting the Var1 as static in the header file which is common to both pet.c and bet.c.
The following is the error log I obtained
libcdr.a(pet.o): In function `.LANCHOR0':
pet.c:(.bss+0x0): multiple definition of `Var1'
build/obj/bet.o:bet.c:(.bss+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
When I checked in google .LANCHOR0 is of type .word in the linker script. I am not able to make out why its called a function and what is its role in multiple definitions error indication ?
.LANCHOR0 isn't a real function, it's just how GCC groups things so it can reference multiple static locations from one reference point.
Constructing a 32-bit address in a register takes multiple instructions, or a PC-relative load of a pointer from a nearby literal pool. The compiler wants to avoid having the address of each individual static (or global) variable in literal pools near code; that would bloat things.
.LANCHOR0, .LANCHOR1, etc. are the names gcc uses for such pointers.
But the result of all this is that apparently variables with static storage look to the assembler like they're defined after a .LANCHOR0 "function".
There's nothing special / useful / interesting going on here as far as debugging your multiple-definitions bug. It's just a consequence of compiling for ARM.

GCC error "<variable> causes a section type conflict"

Why is there a compiler error when attempting to place two (RAM) variables, which only differ by their initialisation values, into the same section?
Problem
The C source:
int __attribute__((section(".in_my_data"))) _foo = 1;
int __attribute__((section(".in_my_data"))) _bar = 0;
The (relevant) GCC compiler output:
mcve/main.c:75:45: error: _bar causes a section type conflict
The linker script contains the following line in the SECTIONS definition, but the (fatal) error is from the compiler, not the linker.
.my_data : { *(.in_my_data) } > data
Further Information
Changing the C source to permit the compiler to use two sections allows the compile to pass, but the linker then generates an error if the two input sections are mapped into the same output section.
The C source:
int __attribute__((section(".in_my_data_nonzero"))) _foo = 1;
int __attribute__((section(".in_my_data_zero"))) _bar = 0;
The linker script:
.my_data : { *(.in_my_data*) } > data
The (relevant) linker output:
Link Error: attributes for input section '.in_my_data_nonzero' conflict
with output section '.my_data'
Swapping the order of the lines in the C source only changes which section (the second to appear in the C source) is in error.
Question
What attribute(s) does the GCC compiler require of a section for a variable that is initialised with zero that it doesn't for one that is initialised with non-zero, or vice versa?
Is the compiler trying to place the variables that are initialised to zero in the .bss section, rather than the .data section for initialised data? Or is there another section for data that is initialised to zero?
Related questions
Similar questions appear cover issues with conflicts between memory types (ROM vs. RAM):
"Section type conflict" in arm embedded, what is it?
How do I resolve a "section type conflict" compile error and best practices for using section attribute with gcc
Getting a "section type conflict" using M2tklib and glcd
... or putting initialised const data in NOLOAD output sections:
"Section type conflict" due to macro definition in GCC 4.8.2
... or remain a mystery as to the cause and may be related:
Section type conflict for identically defined variables
None of the above appear to have an answer that I can apply to issue in this question, as far as I can tell.
By default, GCC places classes of objects in different sections, executable code goes to .text, initialized data to .data, static data to .bss, and some more obscure ones.
If you try to force two objects of different class to belong to the same section, GCC will raise this section error.
The solution is to place them in different sections, and finally, tell the linker to ultimately coalesce these objects in the same section, for example:
.boot : { // target ELF section will contain....
*(.boot) // executable code
*(.boot_rodata) // constant data
*(.boot_bss) // static data
} > BOOT // to finally be place in this area
Caveat: This answer may only apply to the Microchip XC16 compiler.
Research
The compiler assigns attributes to C variables so that they are allocated to specific sections as follows (see Note 1 below for XC16 specific information).
int a = 1; - is assigned to .data.
int b = 0; - is assigned to .bss.
int c; - is assigned to .bss.
The first and last of these make sense: .data is used for initialised data and .bss is used for uninitialised data. However, .bss data is also set to zero by the ANSI C start up (see Note 2).
Answer
It would appear that the compiler is including variables that are initialised, but with a value that equates to all bits 0 in the .bss section as well as all those which are not initialised at all.
According to wikipedia:
An implementation may also assign statically-allocated variables and constants initialized with a value consisting solely of zero-valued bits to the BSS section.
Workaround
GCC has an option -fno-zero-initialized-in-bss which can be used to force all variables that are initialised with zero into the .data section, as stated in this answer. This can be applied on a per-source file basis, but not on individual variables.
Wishful Thinking
It would be nice if there were an __attribute__((**doload**)) that could be applied to force the compiler to place a zero-initialised variable in .data instead of .bss.
Notes
Note 1: The XC16 compiler may use .ndata and .nbss to indicate near data below address 0x8000.
Note 2: Marking a variable with __attribute__((noload)) will result in the variable being excluded from the .bss section. XC16 generates a specific output section, with a (GUID?) unique name for each variable marked as such.

Generating correct .DEF files to export non-static functions AND GLOBALS

Following on from a question about detecting bad linkage to globals across dll boudaries, it turns out that I need to modify a .DEF file generator tool used by the PostgreSQL project so that it correctly emits DATA tags for .DEF entries for global variables.
Problem
I can't seem to find a way, using Microsoft's tools, to get a symbol table listing that differentiates between global variables and functions, and that includes globals that aren't initialized at their definition site.
Ideas?
Broken current approach
The tool loops over dumpbin /symbols output to generate the .DEF file. Unlike nm, which I'm used to, dumpbin /symbols does not appear to emit an entry for each symbol to indicate the symbol type - function, initialized variable, uninitialized variable. It only shows whether the symbol is locally defined or not.
With each dumpbin output line followed by the corresponding definition in the .c file, we have first an initialized global:
00B 00000000 SECT3 notype External | _DefaultXactIsoLevel
int DefaultXactIsoLevel = XACT_READ_COMMITTED;
vs a function with non-static linkage:
022 00000030 SECT5 notype () External | _IsAbortedTransactionBlockState
bool IsAbortedTransactionBlockState(void) {...}
... and for bonus fun, un-initialized globals appear to be shown as UNDEF, just like references to symbols from other compilation units, e.g:
007 00000004 UNDEF notype External | _XactIsoLevel
int XactIsoLevel;
even though this is pre-declared in the header during compilation (with project specific macro hand expanded for readability) as:
extern __declspec(dllexport) int XactIsoLevel;
So... it looks like dumpbin output doesn't contain enough information to generate a correct .DEF file.
Right now gendefs.pl is merrily spitting out a .DEF file that omits globals that aren't initialized, and declares everything else as code (by failing to specify CONSTANT or DATA in the .DEF). For something so broken, it's worked remarkably well.
Fixing it
To produce correct .DEF files, I need a way to determine which symbols are variables.
I looked at using cl.exe's /Fm option, but it's just a passthrough to the linker's /MAP option, and does nothing when you're just generating an object file, not linking it.
I could use a symbol dump tool that produces more useful information like gcc's nm.exe, but that adds extra tool dependencies and seems fragile.
At this point I am not able to simply annotate every exported function with PGDLLIMPORT (the __declspec(dllimport) / __declspec(dllexport) macro used by the project) and stop using a DEF file.
Even if I could I need to find an approach that will cause clear linker errors when PGDLLIMPORT is omitted on an exposed variable.
So. Windows linker/compiler experts. Any ideas?
Well, I must say I was wrong saying that microsoft tools doesn't use symbol type field at all.
1). cl doesn't use it to differentiate actual type info, but it stores information that you need:
0x20 means function
0x00 means not a function
PE/COFF specification, p. 46-47.
You may search for presence/abscence of () after symbol type (notype in your case) in dumpbin's output to find whether it is code or data.
2). Also, cl generates in obj files special section for linker which include export switch for every __declspec(dllexport) symbol in the form /export:symbol[,type].
3). And last, you can specify 'C++' external linkage and get symbols' types because of mangling.
I just add to the other post.
dumpbin has a specific option, namely /headers, that clearly points out the Type as code or data, together with a list of other attributes.

Confused by Unresolved external symbol error

I'm trying to build a wrapper library with VC++'s compiler.
ErlDriver.c
#define __WIN32__
#define DLL_EXPORT __declspec(dllexport)
#include "erl_driver.h"
DLL_EXPORT int _driver_output(ErlDrvPort port, char *buf, int len) {
return driver_output(port, buf, len);
}
build.bat
cl /I%ERL_DRIVER_H% /LD /MD ErlDriver.c
When I attempt to build this, I get the following linker error:
ErlDriver.obj : error LNK2019: unresolved external symbol _WinDynDriverCallbacks referenced in function __driver_output
erl_win_dyn_driver.h (included in erl_driver.h)
typedef struct {
WDD_FTYPE(driver_output) *driver_output;
// a ton more of those
} TWinDynDriverCallbacks;
extern TWinDynDriverCallbacks WinDynDriverCallbacks;
#define driver_output (WinDynDriverCallbacks.driver_output)
So, as you can see, WinDynDriverCallbacks is defined declared.
What could be causing the linker error, then?
No, it's not defined (at least in what you quoted). It's declared. The "extern" keyword means "the definition for this symbol appears in another compilation unit (source file)." You need to be linking with the object file (or library) produced from compiling the source file that defines that symbol.
There is a subtle difference between "declaring" something and "defining" it in C or C++. When you declare it, it tells the compiler that a certain symbol will be defined somewhere else - this can allow the code to use that symbol without needing to see the actual definition. You still have to define the symbol somewhere in the code that is linked in, or else you will get the error message you are seeing.
For example, this is a declaration of the symbol WinDynDriverCallbacks:
extern TWinDynDriverCallbacks WinDynDriverCallbacks;
Your code has this declaration - it allows the code that uses the symbol to successfully compile (but not link).
You need to add a definition somewhere:
TWinDynDriverCallbacks WinDynDriverCallbacks;
The definition must go into a source code file somewhere (not generally in a header file). This tells the compiler to allocate space in the object code for that object and allows the program to link successfully.
I got a very similar problem building a NIF on Windows. Unresolved external symbol _WinDynNifCallbacks. Turns out this is defined by the ERL_NIF_INIT macro and in my case the entire macro needed to be enclosed in a extern C block.
ie this failed
extern "C" ERL_NIF_INIT(...)
while this succeeded
extern "C"
{
ERL_NIF_INIT(...)
}
I strongly suspect this problem is due to the same issue but with the DRIVER_INIT macro for an erlang port driver.
Driver_Init is the main loop that declares "TWinDynDriverCallbacks WinDynDriverCallbacks;" but it's properly declared in the multiple line define for driver_init. You shouldn't need to wrap it in extern "c".
since this thread came up about a million times while trying to setup my barebones erlang port driver i will say this here. I am working out of Joe Armstrong's programming erlang book, chapter 12 interfacing techniques. Using erl5.9 and vs2010.
The code in the book had a omission and a error in example1_lib.c. Though the error is most likely due to the age of the book versus erlang version changes.
Needed to set (#define WIN32) at the very top of example1_lib.c otherwise erlang defaulted to all the Linux options.
Second needed to change (int bufflen) to (ErlDrvSizeT bufflen) in example_drv_output.
After that it built clean.

Resources