rom1 and rom2 have different address map and are not continuous!
some objects have to be placed into rom2.
every time rom1 is linked, objects in rom2 should be the fixed address(rom2). In other words, rom1 should know rom2's symbols' address when linking.
Can I link an elf(rom2) into rom1?
If I understand well :
your system has 2 memories rom1 and rom2
some objects have to be located in rom1, others in rom2
Your link script shall look like the following :
MEMORY
{
rom1 : org=0x10000 len=1024
rom2 : org=0x40000 len=1024
}
SECTIONS
{
.text1 0x10000 : {foo.o(.text) } > rom1
.text2 0x40000 : {bar.o(.text) } > rom2
}
In the part SECTIONS the linker collects the .text sections from foo.o and puts this .text section within the output section .text1 starting at address 0x10000 in rom1.
Similarly, it collects the .text section from bar.o and puts it in rom2.
Related
I have a huge DDR memory (2GB) with huge access time and tiny internal RAM (1MB) with tiny access time. At this moment I have whole .bss section in DDR. The .bss section contains one often used variable from external library. How can I move it from slow DDR to fast RAM? There is no way to fit whole .bss in RAM and also I can't modify external library.
Disassembly of section .bss:
8000008c <some_variable>
.bss (NOLOAD) : {
. = ALIGN(4);
__bss_start = .;
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > DDR
I tried someting like that, but its not work.
.bssFAST (NOLOAD) : {
. = ALIGN(4);
file.o:some_variable(.bss)
. = ALIGN(4);
} > RAM
I tried someting like that, but its not work.
That couldn't work: the linker doesn't work at the variable level, it works on sections.
If foo.os .bss section is not too large, you may be able to move that entire section into .bssFAST.
If you can't do that, your only other choice is to binary-patch foo.o such that:
It has a new .bssFAST section (objcopy --add-section should work) and
Change some_variable so it's in that new section (this should be relatively easy -- updating .st_shndx should do it).
I am trying to understand the GCC link script and create a small demo to practice , however I got the "syntax error" from ld. I appreciate any comments or suggestions. Thank you so much!
hello.c
__attribute__((section(".testsection"))) volatile int testVariable;
hello.ld
MEMORY {
TEST_SECTION: ORIGIN = 0x43840000 , LENGTH = 0x50
}
SECTIONS{
.testsection: > TEST_SECTION /* Syntax error here*/
}
compile command
gcc -T hello.ld -o hello hello.o
c:/gnu/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe:../hello.ld:20: syntax error
collect2.exe: error: ld returned 1 exit status
Original post
MEMORY {
TEST_SECTION: ORIGIN = 0x43840000 LENGTH = 0x50
}
SECTIONS{
.testsection: > TEST_SECTION
}
Solution
MEMORY {
TEST_SECTION: ORIGIN = 0x43840000, LENGTH = 0x50
}
SECTIONS{
.testsection: { *(.testsection*) } > TEST_SECTION
}
I think it was missing two things.
First the comma between the origin value and LENGTH.
Second a section command was missing. I don't think the GNU linker script syntax allows for that, you probably need to put something in there anyway to have this be useful. You could try
.testsection: { } > TEST_SECTION
but my guess without trying it is that you wouldn't end up with anything in that memory.
Edit
After doing an experiment:
so.s
.text
add r0,r0,r0
add r1,r2,r3
add r1,r1,r1
add r2,r2,r2
so.ld
MEMORY
{
bob : ORIGIN = 0x30000000, LENGTH = 0x1000
ted : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.hello : { *(.text*) } > bob
.world : { } > ted
.text : { } > ted
}
Disassembly of section .hello:
30000000 <.hello>:
30000000: e0800000 add r0, r0, r0
30000004: e0821003 add r1, r2, r3
30000008: e0811001 add r1, r1, r1
3000000c: e0822002 add r2, r2, r2
As I suspected, first I already new the names in MEMORY are whatever you want, as you saw as well, RAM, ROM, etc are not special names just can't use reserved names if any. I suspected that SECTIONS worked the same way the thing on the left is a new name you are creating for the output. This built and linked just fine (not a real program obviously just enough to get the tools to do a demonstration).
The linker did not complain, but at the same time since there was nothing actually placed in ted then nothing was placed in that memory space in the output binary. .hello and .text don't have to match, one is an output name one is an input name, very often for simple stuff folks make them match, why create a new name. Only did it here for demonstration purposes to show that by using the same name on the left does not automatically include the input section to the output.
I highly recommend doing experiments like this and using tools like readelf and objdump and others to examine what is going on (as well as reading the documentation for the scripting language).
There are a lot of logs and other stuff below, so to skip to the punchline: I have a linker script and am setting variables within it, and using these variables to set up memory sections. But it seems like these variables are always being set to 0 no matter what I set them to in the script.
I am writing a linker script, trying to add two new memory sections to my output elf for an embedded systems application. I am trying to chop off the first bit of the preexisting RAM memory section, change the size of RAM accordingly, and place my new sections there.
Previously, using the nrf52840 development board and this library, I can modify the linker script for one of the example applications as so:
SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)
__NewSection1Start = 0x20000000;
__TotalLength = 0x1000;
__NewSection2Length = __TotalLength / 2;
__NewSection1Length = __TotalLength / 2;
__NewSection2Start = __NewSection1Start + __NewSection1Length;
MEMORY
{
FLASH (rx) : ORIGIN = 0x0, LENGTH = 0xff000
NEWSECTION1 (rwx) : ORIGIN = __NewSection1Start, LENGTH = __NewSection1Length
NEWSECTION2 (rwx) : ORIGIN = __NewSection2Start, LENGTH = __NewSection2Length
RAM (rwx) : ORIGIN = 0x20000000 + __TotalLength, LENGTH = 0x40000
}
FLASH_PAGE_SIZE = 4096;
FLASH_DATA_PAGES_USED = 4;
SECTIONS
{
.newsection1 :
{
KEEP (*(.newsection1));
} > NEWSECTION1
.newsection2 :
{
KEEP (*(.newsection2));
} > NEWSECTION2
}
...
And this works perfectly. Recently, I have needed to port to the nrf9160 using the Zephyr RTOS, so I began using the NordicPlayground nrf library built on top of Zephyr at this link, modifying one of the sample apps in there. In trying to rewrite the program for that board and environment, using a technique similar to this, I did a similar thing with the Zephyr linker script, modifying it as before. The build process somehow takes what I have done and generates the file build/spm/zephyr/linker.cmd in the build output folder:
__TotalLength = 0x1000;
__NewSection1Start = 0x20000000;
__NewSection2Length = __TotalLength / 2;
__NewSection1Length = __TotalLength / 2;
__NewSection2Start = __NewSection1Start + __NewSection1Length;
MEMORY
{
FLASH (rx) : ORIGIN = 0x0, LENGTH = 0xc000
SRAM (wx) : ORIGIN = 0x20000000 + __TotalLength, LENGTH = (64 * 1K) - __TotalLength
NEWSECTION1 (rwx) : ORIGIN = __NewSection1Start, LENGTH = __NewSection1Length
NEWSECTION2 (rwx) : ORIGIN = __NewSection2Start, LENGTH = __NewSection2Length
IDT_LIST (wx) : ORIGIN = (0x20000000 + (64 * 1K)), LENGTH = 2K
}
ENTRY("__start")
SECTIONS
{
.newsection1 :
{
KEEP (*(.newsection1));
} > NEWSECTION1
.newsection2 :
{
KEEP (*(.newsection2));
} > NEWSECTION2
}
...
However, although I thought these two scripts should behave the same, trying to compile and link with the nrf9160 version with the Zephyr RTOS throws this error:
riley#riley-Blade:~<code_base>/nrf/samples/nrf9160/example_app$ west build -b nrf9160_pca10090ns
source directory: /home/riley<code_base>/nrf/samples/nrf9160/example_app
build directory: /home/riley<code_base>/nrf/samples/nrf9160/example_app/build
BOARD: nrf9160_pca10090ns (origin: CMakeCache.txt)
[6/17] Linking C executable spm/zephyr/spm_zephyr_prebuilt.elf
Memory region Used Size Region Size %age Used
FLASH: 32 KB 48 KB 66.67%
SRAM: 10000 B 60 KB 16.28%
NEWSECTION1: 0 GB 2 KB 0.00%
NEWSECTION2: 0 GB 2 KB 0.00%
IDT_LIST: 40 B 2 KB 1.95%
[12/17] Linking C executable zephyr/zephyr_prebuilt.elf
FAILED: zephyr/zephyr_prebuilt.elf
: && ccache /home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gcc zephyr/CMakeFiles/zephyr_prebuilt.dir/misc/empty_file.c.obj -o zephyr/zephyr_prebuilt.elf -Wl,-T zephyr/linker.cmd -Wl,-Map=/home/riley<code_base>/nrf/samples/nrf9160/example_app/build/zephyr/zephyr.map -u_OffsetAbsSyms -u_ConfigAbsSyms -Wl,--whole-archive app/libapp.a zephyr/libzephyr.a zephyr/arch/arm/core/libarch__arm__core.a zephyr/arch/arm/core/cortex_m/libarch__arm__core__cortex_m.a zephyr/arch/arm/core/cortex_m/mpu/libarch__arm__core__cortex_m__mpu.a zephyr/lib/libc/minimal/liblib__libc__minimal.a zephyr/subsys/net/libsubsys__net.a zephyr/subsys/net/ip/libsubsys__net__ip.a zephyr/drivers/gpio/libdrivers__gpio.a zephyr/drivers/serial/libdrivers__serial.a zephyr/modules/nrf/lib/bsdlib/lib..__nrf__lib__bsdlib.a zephyr/modules/nrf/lib/at_host/lib..__nrf__lib__at_host.a zephyr/modules/nrf/drivers/at_cmd/lib..__nrf__drivers__at_cmd.a /home/riley<code_base>/nrfxlib/bsdlib/lib/cortex-m33/hard-float/libbsd_nrf9160_xxaa.a -Wl,--no-whole-archive zephyr/kernel/libkernel.a zephyr/CMakeFiles/offsets.dir/arch/arm/core/offsets/offsets.c.obj -L"/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/thumb/v8-m.main+fp/hard" -L/home/riley<code_base>/nrf/samples/nrf9160/example_app/build/zephyr -lgcc -Wl,--print-memory-usage /home/riley<code_base>/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/hard-float/liboberon_3.0.0.a -lc -mthumb -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -Wl,--gc-sections -Wl,--build-id=none -Wl,--sort-common=descending -Wl,--sort-section=alignment -nostdlib -static -no-pie -Wl,-X -Wl,-N -Wl,--orphan-handling=warn -mabi=aapcs -march=armv8-m.main+dsp libspmsecureentries.a && :
Memory region Used Size Region Size %age Used
FLASH: 110428 B 976 KB 11.05%
SRAM: 24608 B 124 KB 19.38%
NEWSECTION1: 264 B 0 GB inf%
NEWSECTION2: 1 B 0 GB inf%
IDT_LIST: 120 B 2 KB 5.86/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: zephyr/zephyr_prebuilt.elf section `.newsection1' will not fit in region `NEWSECTION1'
/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: zephyr/zephyr_prebuilt.elf section `.newsection2' will not fit in region `NEWSECTION2'
/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: section .newsection2 LMA [0000000000000000,0000000000000000] overlaps section .newsection1 LMA [0000000000000000,0000000000000107]
/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: region `NEWSECTION1' overflowed by 264 bytes
/home/riley/gcc-arm-none-eabi-9-2019-q4-major/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: region `NEWSECTION2' overflowed by 1 byte
collect2: error: ld returned 1 exit status
%
ninja: build stopped: subcommand failed.
ERROR: command exited with status 1: /home/riley/.local/bin/cmake --build /home/riley<code_base>/nrf/samples/nrf9160/example_app/build
This is really strange for me, because this ouptut makes it seem like NEWSECTION1 and NEWSECTION2 have 0 length and both start at address 0x0, but this definitely should not be the case looking at the used linker script. To further make this confusing, if I replace __NewSection1Length with 0x500, or something like that, then the memory section will be 0x500B long, meaning that it seems like the error is that using variables in this linker script are being ignored or set to 0? Any help would be very much appreciated.
Some of the more complicated features of Zephyr like bootloaders and SPM (secure partition manager) actually build using independent board definitions, linker scripts, and project configurations. Even though they all happen from one call to west build or ninja or make or whatever build tool you are configured with, they can sometimes end up mismatched.
You can see this if you go into the build output directory and notice that there will be multiple sub-directories with names like spm and mcuboot and zephyr. Each of these sub-directories will contain their own object files, map files, linker scripts, etc. The zephyr directory is the top level one that contains the build/link work for your final application and will merge in the pre-compiled binaries from the others. What I think is happening is that the prj.conf changes you made to create the custom sections in your application are only affecting one of these sub-builds. You likely need to find the prj.conf files for the other ones and modify them similarly.
What exactly do the BLOCK and ALIGN commands do in a linker script? The names seem to speak for themselves; but, I don't see exactly how they are affecting the resulting OS image.
The linker script below is based on the example given by the OSDev Bare Bones example (http://wiki.osdev.org/Bare_Bones).
(1) In the resulting image, the .rodata section begins at address 0x1400, and the .data section begins at 0x2400. Shouldn't the BLOCK(4K) command place .rodata at 0x1000 (or some other multiple of 4KB)?
(2) What does ALIGN(4K) do? The documentation (https://www.math.utah.edu/docs/info/ld_3.html) indicates that it is just a calculation that returns the current location adjusted to the nearest 4K boundary. However, the documentation for SECTION doesn't indicate a place for a parameter after the colon (other than an AT command, which isn't present here).
(3) In either case, why have both BLOCK and ALIGN?
SECTIONS
{
. = 0x7c00;
__start = .;
.text :
{
*(.boot)
/*
Magic bytes. 0x1FE == 510.
We could add this on each Gas file separately with `.word`,
but this is the perfect place to DRY that out.
*/
. = 0x1FE;
SHORT(0xAA55)
/*
This is only needed if we are going to use a 2 stage boot process,
e.g. by reading more disk than the default 512 bytes with BIOS `int 0x13`.
*/
*(.stage2)
*(.text)
}
/* Read-only data. */
.rodata BLOCK(4K) : ALIGN(4K)
{
LONG(0x11223344) /* just a marker so I can see where the linker places this section */
*(.rodata)
}
/* Read-write data (initialized) */
.data BLOCK(4K) : ALIGN(4K)
{
LONG(0x44332211)
*(.data)
}
I am trying to see the IMAGE_DOS_HEADER structure using the 'dt' command in windbg:
0:001> dt ntdll!IMAGE_DOS_HEADER
**Symbol ntdll!IMAGE_DOS_HEADER not found**
I searched and found that others have been able to do this:
MSDN Blogs > Junyoung's Blog > Portable Executable File Format on Memory Dump
0:000> dt IMAGE_DOS_HEADER 77c00000
ntdll!IMAGE_DOS_HEADER
+0x000 e_magic : 0x5a4d ? MZ
+0x002 e_cblp : 0x90
+0x004 e_cp : 3
+0x006 e_crlc : 0
+0x008 e_cparhdr : 4
+0x00a e_minalloc : 0
+0x00c e_maxalloc : 0xffff
+0x00e e_ss : 0
+0x010 e_sp : 0xb8
+0x012 e_csum : 0
+0x014 e_ip : 0
+0x016 e_cs : 0
+0x018 e_lfarlc : 0x40
+0x01a e_ovno : 0
+0x01c e_res : [4] 0
+0x024 e_oemid : 0
+0x026 e_oeminfo : 0
+0x028 e_res2 : [10] 0
+0x03c e_lfanew : 232
Is it possible to add the missing symbol to public symbols of ntdll so that I can access the data structure fields in a windbg debugging session?
This is really weird - I tried the following and got different results on a win7 and on winxp systems -
WinXP:
0:015> dt ntdll!*HEADER*
ntdll!_IMAGE_NT_HEADERS
ntdll!_IMAGE_FILE_HEADER
ntdll!_IMAGE_OPTIONAL_HEADER
ntdll!_SLIST_HEADER
ntdll!_DISPATCHER_HEADER
ntdll!_IMAGE_SECTION_HEADER
Win7:
0:000> dt ntdll!*HEADER*
ntdll!_IMAGE_NT_HEADERS
ntdll!_IMAGE_FILE_HEADER
ntdll!_IMAGE_OPTIONAL_HEADER
ntdll!_IMAGE_DOS_HEADER
ntdll!_SLIST_HEADER
ntdll!_DISPATCHER_HEADER
ntdll!_MM_PAGE_ACCESS_INFO_HEADER
ntdll!_WHEA_ERROR_RECORD_HEADER
ntdll!_HEAP_USERDATA_HEADER
ntdll!_HEAP_USERDATA_HEADER
ntdll!_WHEA_ERROR_RECORD_HEADER_VALIDBITS
ntdll!_WHEA_ERROR_RECORD_HEADER_FLAGS
ntdll!_XSAVE_AREA_HEADER
So it seems that the _IMAGE_DOS_HEADER symbol is stripped from the public symbols of winxp's ntdll.dll - my question remains - how can I add the symbol if I know the structure to a public symbols dll of a dll I don't have the sources for?
This happens, it can be quite frustrating actually (though they've done a good job cleaning a lot of these up).
You can add types to existing PDBs, though it requires that you have the Visual C compiler available (either from Visual Studio or the WDK). I outline the steps in my response here:
http://www.osronline.com/showthread.cfm?link=193747
We're using the kernel there, though you have the same steps. The differences will be:
1) Look for ntdll instead of nt
2) You'll need to write a C file with the definition of the structure that you want.
-scott
you can also check this thread it shows how to add types to
http://www.woodmann.com/forum/showthread.php?10295-Mysteries-of-win32k-amp-GDI&p=72632&viewfull=1#post72632
post # 21
They're not missing, you just don't have your symbol path configured.
Check the following Microsoft KB, if that doesn't work, you may have an odder problem.
One way to make sure you're debugging with symbols is the lm command.
The output without debug symbols is likely to look like this:
lm
start end module name
01000000 01014000 notepad (no symbols)
74720000 7476b000 MSCTF (export symbols) C:\WINDOWS\system32\MSCTF.dl
Whilee the output for lm with debug symbols will be:
lm
start end module name
01000000 01014000 notepad (pdb symbols) e:\LocalSymbols\notepad.pdb\15800B8231AF4FDE85232D42B267D3E51\notepad.pdb