I am trying to access data from a file that I load in via tftp. I'm using an AM3358 processor
tftp 81000000 mydata
and I can see the data being correctly loaded
=> md 81000000
81000000: 00004000 00000000 00002000 00000400 .#....... ......
In the u-boot code, I create a pointer to this address and then attempt to de-reference it, but the value is incorrect which makes me think I'm using the incorrect address
unsigned long addr = 0x81000000;
uint32_t *ptr = &addr;
uint32_t val = *(ptr+0);
printf("addr %ul val: %ul", addr, val);
Furthermore, I'm trying to load the address of mydata into a 32-bit LCD register, but the physical address of 0x81000000 is beyond that of a 32-bit number. I believe I'm just confused as to what address mapping is involved here.
bdi yields
=> bdi
arch_number = 0x00000000
boot_params = 0x80000100
DRAM bank = 0x00000000
-> start = 0x80000000
-> size = 0x20000000
baudrate = 115200 bps
TLB addr = 0x9fff0000
relocaddr = 0x9ffb4000
reloc off = 0x1f7b4000
irq_sp = 0x9df8ba90
sp start = 0x9df8ba80
Early malloc usage: 4a8 / 1000
fdt_blob = 0x9df8bea0
Why would 0x81000000 not be a valid 32 bit number ?
0x00000000 <= 0x81000000 <= 0xFFFFFFFF.
I think there may be an error in your logic: you are initializing ptrwith the address of addr, not the address of its content.
The correct code would rather be something like:
uint32_t addr = 0x81000000;
uint32_t *ptr = (uint32_t*)(uintptr_t) addr;
uint32_t val = *(ptr+0);
printf("addr %ul val: %ul", addr, val);
This can be tested on your PC - you may need to add support for building 32 bit applications, i.e. execute sudo apt-get install gcc-multilib on Ubuntu.
ptr.c:
#include <stdio.h>
#include <stdint.h>
int
main ()
{
uint32_t addr = 0x81000000; // gcc 9.3.0 is complaining about uint32_t *ptr = &addr;
// your code
{
uint32_t *ptr = &addr;
printf ("%p\n", ptr);
}
// correct code
{
uint32_t *ptr = (uint32_t *) (uintptr_t) addr;
printf ("%p\n", ptr);
}
}
gcc -m32 -o ptr ptr.c
./ptr
0xff83bc60
0x81000000
This would be why you cannot access the content of the file you transferred using TFTP, you are reading from an incorrect, but valid address.
A Bootloader and an application is working fine.
The bootloader loads the application, and then jumps into it.
The problem: I need to use different linker script to either have the app standalone or bootloader compatible.
I believe it is because the memory segment is not correctly defined for kseg0_program_mem, kseg0_boot_mem & kseg1_boot_mem.
//_RESET_ADDR = 0xBFC00000; <- work without bootloader
_RESET_ADDR = 0x9D000480; <- work with bootloader
[....]
MEMORY
{
kseg0_program_mem (rx) : ORIGIN = 0x9D000000 + 0x800, LENGTH = 0x100000 - 0x800
kseg0_boot_mem : ORIGIN = 0x9D000000, LENGTH = 0x0
debug_exec_mem : ORIGIN = 0x9FC20490, LENGTH = 0x3B20
kseg0_boot_mem : ORIGIN = 0x9FC20490, LENGTH = 0x0
kseg1_boot_mem : ORIGIN = 0x9D000000, LENGTH = 0x480
kseg1_boot_mem_4B0 : ORIGIN = 0xBFC004B0, LENGTH = 0x3B00
config_BFC03FC0 : ORIGIN = 0xBFC03FC0, LENGTH = 0x4
I am trying to create a chain of pointer addresses, with the first pointing to address of the next, and so on.
For example, char *a 's address is 0x1, char *b address is 0x2, char *x address is 0x3. I want to link a->b->c, so that my hope is to store value 0x2 into 0x1 memory address, value 0x3 into 0x2 memory address.
I have following codes:
#define PUT(p, val) (*(unsigned long *)(p) = (val))
#define SET_NEXT_PTR(p, ptr) (*(char**)(p) = (char*)((unsigned long)(ptr)))
void chain(char* bp){
char *first = mem_sbrk(size);
char *second =mem_sbrk(size);
PUT(first, (unsigned long)bp);
PUT(bp, *second);
}
When I run gdb, and exam those memory address. After call mem_sbrk for first and second.
(gdb) x /x first
0x7ffff661c020: 0x00000000
(gdb) x /x bp
0x7ffff661b020: 0x00000000
(gdb) x/x second
0x7ffff661d020: 0x00000000
After call PUT macro:
(gdb) x/x second
0x7ffff661d020: 0x00000000 0x00000000
(gdb) x /2x first
0x7ffff661c020: 0xf661b020 0x00007fff
(gdb) p first
0x7ffff661c020 " \260a\366\377\177"
(gdb) x /2x bp
0x7ffff661b020: 0xf661d020 0x00007fff
It seems working. But I wonder how can I convert those memory address to a pointer. Since entire memory address stores into 0x7ffff661d020 and 0x7ffff661d024. When I use p first, it returns a meaningless string.
Second question, in gdb when I call
(gdb) p &bp
(char **) 0x7fffffffe3e8
I wonder what is 0x7fffffffe3e8? I thought & is for getting memory address,I expect gdb shows
(void*) 0x7ffff661b020
Third question what is difference between
#define PUT(p, val) (*(unsigned long *)(p) = (val))
#define SET_NEXT_PTR(p, ptr) (*(char**)(p) = (char*)((unsigned long)(ptr)))
I am using gcc to create an hex file por a pic32 microcontroller and I need to place the configuration words at special memory addresses in the program flash.
I am using this simple linker script:
MEMORY {
boot_flash : ORIGIN = 0x1FC00000, LENGTH = 0xBF0
sfr : ORIGIN = 0x1F800000, LENGTH = 0x100000
program_flash : ORIGIN = 0x1D000000, LENGTH = 0x20000
ram : ORIGIN = 0x00000000, LENGTH = 0x8000
config0 : ORIGIN = 0xBFC02FFC, LENGTH = 0x4
config1 : ORIGIN = 0xBFC02FF8, LENGTH = 0x4
config2 : ORIGIN = 0xBFC02FF4, LENGTH = 0x4
config3 : ORIGIN = 0xBFC02FF0, LENGTH = 0x4
}
SECTIONS {
.text : {
*( .text )
} >boot_flash
.text : {
*(.text)
} >program_flash
.bss : {
*( .bss )
} >ram
.data : {
*( .data )
} >ram
.config0 : {
*( .config0 )
} >config0
.config1 : {
*( .config1 )
} >config1
.config2 : {
*( .config2 )
} >config2
.config3 : {
*( .config3 )
} >config3
}
Then, I compile this simple code:
...
uint32_t config0 __attribute__ ((section(".config0"))) = 0xFFFFFFFF;
uint32_t config1 __attribute__ ((section(".config1"))) = 0xFFFFAF0F;
uint32_t config2 __attribute__ ((section(".config2"))) = 0xFFFFFDFF;
uint32_t config3 __attribute__ ((section(".config3"))) = 0xFFFFFDFF;
...
An finally I check with mips-elf-objdump the resulting ELF file. The code and the data are ok but there are no .config sections in the output ELF.
What am I doing wrong?
The code is ok. The problem was on mips-elf-objdump: I was using it with the -d option that does not show me the other ELF sections :-/
Sorry and thanks you your help! :-)
Try adding some code somewhere in the app to reference the config items, like this:
volatile uint32_t dummy;
dummy = config0;
dummy = config1;
dummy = config2;
dummy = config3;
You may find that the linker has been discarding them because they're not referenced - you can tell the linker not to discard unused symbols, but I have had problems with recent versions with sections being discarded regardless.
I am writing code to use a library called SCIP (solves optimisation problems). The library itself can be compiled in two ways: create a set of .a files, then the binary, OR create a set of shared objects. In both cases, SCIP is compiled with it's own, rather large, Makefile.
I have two implementations, one which compiles with the .a files (I'll call this program 1), the other links with the shared objects (I'll call this program 2). Program 1 is compiled using a SCIP-provided makefile, whereas program 2 is compiled using my own, much simpler makefile.
The behaviour I'm encountering occurs in the SCIP code, not in code that I wrote. The code extract is as follows:
void* BMSallocMemory_call(size_t size)
{
void* ptr;
size = MAX(size, 1);
ptr = malloc(size);
// This is where I call gdb print statements.
if( ptr == NULL )
{
printf("ERROR - unable to allocate memory for a SCIP*.\n");
}
return ptr;
}
void SCIPcreate(SCIP** A)
{
*A = (SCIP*)BMSallocMemory_call(sizeof(**(A)))
.
.
.
}
If I debug this code in gdb, and step through BMSallocMemory_call() in order to see what's happening, and view the contents of *((SCIP*)(ptr)), I get the following output:
Program 1 gdb output:
289 size = MAX(size, 1);
(gdb) step
284 {
(gdb)
289 size = MAX(size, 1);
(gdb)
290 ptr = malloc(size);
(gdb) print ptr
$1 = <value optimised out>
(gdb) step
292 if( ptr == NULL )
(gdb) print ptr
$2 = <value optimised out>
(gdb) step
290 ptr = malloc(size);
(gdb) print ptr
$3 = (void *) 0x8338448
(gdb) print *((SCIP*)(ptr))
$4 = {mem = 0x0, set = 0x0, interrupt = 0x0, dialoghdlr = 0x0, totaltime = 0x0, stat = 0x0, origprob = 0x0, eventfilter = 0x0, eventqueue = 0x0, branchcand = 0x0, lp = 0x0, nlp = 0x0, relaxation = 0x0, primal = 0x0, tree = 0x0, conflict = 0x0, cliquetable = 0x0, transprob = 0x0, pricestore = 0x0, sepastore = 0x0, cutpool = 0x0}
Program 2 gdb output:
289 size = MAX(size, 1);
(gdb) step
290 ptr = malloc(size);
(gdb) print ptr
$1 = (void *) 0xb7fe450c
(gdb) print *((SCIP*)(ptr))
$2 = {mem = 0x1, set = 0x8232360, interrupt = 0x1, dialoghdlr = 0xb7faa6f8, totaltime = 0x0, stat = 0xb7fe45a0, origprob = 0xb7fe4480, eventfilter = 0xfffffffd, eventqueue = 0x1, branchcand = 0x826e6a0, lp = 0x8229c20, nlp = 0xb7fdde80, relaxation = 0x822a0d0, primal = 0xb7f77d20, tree = 0xb7fd0f20, conflict = 0xfffffffd, cliquetable = 0x1, transprob = 0x8232360, pricestore = 0x1, sepastore = 0x822e0b8, cutpool = 0x0}
The only reason I can think of is that in either program 1's or SCIP's makefile, there is some sort of option that forces malloc to initialise memory it allocates. I simply must learn why the structure is initialised in the compiled implementation, and is not in the shared object implementation.
I doubt the difference has to do with how the two programs are built.
malloc does not initialize the memory it allocates. It may so happen by chance that the memory you get back is filled with zeroes. For example, a program that's just started is more likely to get zero-filled memory from malloc than a program that's been running for a while and allocating/deallocating memory.
edit You may find the following past questions of interest:
malloc zeroing out memory?
Create a wrapper function for malloc and free in C
When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?
Initialization of malloc-ed memory may be implementation dependent. Implementations are free not to do so for performance reasons, but they could initialize the memory for example in debug mode.
One more note. Even uninitialized memory may contain zeros.
On Linux, according to this thread, memory will be zero-filled when first handed to the application. Thus, if your call to malloc() caused the program's heap to grow, the "new" memory will be zero-filled.
One way to verify is of course to just step into malloc() from your routine, that should make it pretty clear whether or not it contains code to initialize the memory, directly.