I would like to locate a table of constant values with application data (equipment information), preferably at the end of the vector table.
In startup.s I do the following:
MODULE ?cstartup
;; Forward declaration of sections.
SECTION CSTACK:DATA:NOROOT(3)
SECTION .intvec:CODE:NOROOT(2)
EXTERN __iar_program_start
EXTERN SystemInit
PUBLIC __vector_table
PUBLIC _InfoEqData
DATA
__vector_table
DCD sfe(CSTACK)
DCD Reset_Handler ; Reset Handler
/* ............... */
DCD LCD_IRQHandler ; LCD
DCD USB_IRQHandler ; USB
__vector_table_end
_InfoEqData EQU __vector_table_end
In main.c I do the following:
#pragma location = _InfoEqData
const EqIdentify_t eqIdentify = { ... }
When I compile the code shows the following (expected) error
Error[Pe020]: identifier "_InfoEqData" is undefined ... \tst_vBus_main.cpp 25
How do I tell the compiler to find that identifier from startup.s?
Thanks in advance
The IAR toolchain supports #pragma location1 only to fix data at absolute addresses given by literal numbers2 or segment names3.
From my point of view, you should define an own segment in the linker command file3 and locate it according to your requirements.
1
IAR C/C++ Compiler User Guide for the 8051Microcontroller Architecture (C8051-7), Seventh edition: March 2017, page 372.
2
ibid., Seventh edition: March 2017, page 260.
3
ibid., Seventh edition: March 2017, page 262.
4
IAR Linker and Library Tools Reference Guide (XLINK-5001), April 2010, page 21.
I'm trying to compile the same lib on two x86 separate machines.
Both use the same toolchain (exactly same set of files) but have different Glibc versions.
When I run command LD_DEBUG=libs /lib64/ld-linux-x86-64.so.2 --list ./libl2ps.so I notice the following discrepancy between the 2 Linux loaders:
Machine 1 (with Glibc 2.12):
19943: find library=libm.so.6 [0]; searching
19943: search path=/ebs/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64:...:/ebs/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/. (RPATH from file ./libl2ps.so)
19943: trying file=/ebs/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm.so.6
19943:
19943: find library=libgcc_s.so.1 [0]; searching
...
In this case the Linux loader selects lib libm.so.6 from the toolchain path based on RPATH of lib libl2ps.so.
Machine 2 (with Glibc 2.17):
10699: find library=libm.so.6 [0]; searching
10699: search path=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64:/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/lib64:/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib:/home/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/. (RPATH from file ./libl2ps.so)
10699: trying file=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm.so.6
10699: trying file=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/lib64/libm.so.6
10699: trying file=/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib/libm.so.6
10699: trying file=/home/frperies/repo/gnb/uplane/build_bbp/l2_ps/build/./libm.so.6
10699: search cache=/etc/ld.so.cache
10699: trying file=/lib64/libm.so.6
As for Machine 1, the loader attempts from RPATH of libl2ps.so to select lib libm.so.6 from toolchain path but skip it for some reason and try further other paths. Finally it selects libm.so.6from the system path /lib64/.
The RPATH of the 2 libs lib2ps.so are exactly the same. The two files libm.so.6 are also exactly the same on both machines (checked with md5sum).
I don't understand this differences of behavior between the 2 Linux loaders.
Do you see any reason what would explain this discrepancy ?
Thank you very much for your answers.
Update:
Thank you yugr for your answer.
Output of readelf -h gives only differences on fields "Entry point address" and "Start of section headers" and there is no other differences so I think it will not help.
Regarding using dlopen()/dlerror(), I've done a little executable with the following statement:
dlopen("/home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so", RTLD_LAZY);
On machine 1 it works as expected:
C++ dlopen demo
Opening libm-2.28.so...
Closing library...
On machine 2 it fails and dlerror() gives the following output:
Cannot open library: /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so: cannot open shared object file: No such file or directory
but the file libm-2-28.so really exists on my file system:
$ ls -l /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic-linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so
-rwxr-xr-x 1 frperies linseeusers_lte_espoo 1682944 Oct 5 13:50 /home/frperies/repo/gnb/uplane/build/prefix-root/asik-x86_64-ps_lfs-dynamic- linker-on/toolchain/sysroots/core2-64-pc-linux-gnu/usr/lib64/libm-2.28.so
This is very weird, what could lead to this situation ???
Thanks
Update 2:
That is true that I haven't pointed out that machine 1 is a RHEL6.8 distro while machine 2 is RHEL7.4 distro. I (naively?) didn't think this really matters...
On machine 1:
$ cat /proc/sys/kernel/osrelease
4.4.115-1.NSN.el6.x86_64
$ uname -a
Linux sq24-3 4.4.115-1.NSN.el6.x86_64 #1 SMP Mon Feb 12 12:35:46 CET 2018 x86_64 x86_64 x86_64 GNU/Linux
$ readelf -n libl2ps.so
Notes at offset 0x00000270 with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: b598468830fdf2f61eda25553b9a367c4d28cdc9
On machine 2:
$ cat /proc/sys/kernel/osrelease
3.10.0-693.el7.x86_64
$ uname -a
Linux localhost.localdomain 3.10.0-693.el7.x86_64 #1 SMP Thu Jul 6 19:56:57 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux
$ readelf -n libl2ps.so
Displaying notes found at file offset 0x00000270 with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 5829181bc0502233748149369108915ea7b10e8f
Does it help ?
Thanks
Update 3:
$ readelf -n libm.so.6
Notes at offset 0x00000238 with length 0x00000024:
Owner Data size Description
GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
Build ID: 0d84c7247dd76008c096719043e5592735a1c4bd
Notes at offset 0x0000025c with length 0x00000020:
Owner Data size Description
GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
OS: Linux, ABI: 4.4.0
So, how to interpret this ABI version number set to 4.4.0 ??
Thanks
Thank you yugr and Employed Russian for your answers!!
I will give it a try by upgrading my Kernel version on Machine 2.
Thanks
Regards
The error message that you see is the infamously confusing ENOENT errno. I see two instances of it in dl-load.c:
checking OS compatibility
loading non-setuid to setuid process
I suspect the first one fails in your case which would mean that OS kernel is incompatible between two machines. ld.so manpage indeed says that
Each shared object can inform the dynamic linker of the
minimum kernel ABI version that it requires. (This
requirement is encoded in an ELF note section that is viewable
via readelf -n as a section labeled NT_GNU_ABI_TAG.) At run
time, the dynamic linker determines the ABI version of the
running kernel and will reject loading shared objects that
specify minimum ABI versions that exceed that ABI version.
NT_GNU_ABI_TAG is 4.4.0 which means that you run a program expecting a minimum 4.4 kernel on a 3.10 kernel. Theoretically newer Glibc should run on older kernels as well but in your case Glibc was probly built with explicit --enable-kernel flag which prevents it's usage on kernels before 4.4 (see e.g. this explanation of --enable-kernel).
As a workaround, you may try to fool Glibc by overriding kernel version on machine 2 via
export LD_ASSUME_KERNEL=4.4.0
but it may not work if libm makes 4.4-specific syscalls that are not really present on 3.10.
I have dumped the RTL generated as intermediate using "-fdump-final-insns" flag in compilation of a C Program using gcc but i need the optimized version of it, i.e. the resultant RTL after optimization phase of compiler. How can i get it ?
Example -
Register Transfer Language (RTL)
(insn 14 12 15 (nil) (set (reg:CCZ 17
(compare:CCZ (mem/f:SI (plus:SI (reg/f:SI 54 virtual-stack-vars)
(const_int -4 [0xfffffffc])) [0 i+0 S4 A32])
(const_int 99 [0x63]))) -1 (nil)
(nil))
Optimized RTL -
(insn 14 12 15 (nil) (set (reg:CCZ 17 flags)
(compare:CCZ (reg/v:SI 61 [ i ])
(const_int 99 [0x63]))) -1 (nil)
(nil))
For this purpose, you can use flags:
gcc foo.c -da -dp -fdump-tree-all-raw-lineno
Where:
-da produce all RTL dumps
-dp annotate the assembler output with a comment indicating which
patterns and alternatives are used.
-fdump-tree-all-raw-lineno Enables showing line numbers for statements.
This will create about 167 files, each of them means different stages of GIMPLE and RTL passes, optimizations and so on.
Here is simple explanation is what's going on:
https://www.cse.iitb.ac.in/~uday/courses/cs715-09/gcc-rtl.pdf
Look at last two number 306 and 307, there is the final, optimized phase of compiler before parse it into assembler.
foo.c.306r.final
foo.c.307r.finish
You can also use flags -S with -dA
Where:
-S produces assembler output
-dA annotate the assembler output with miscellaneous debugging information
and in foo.s you can view a connection between RTL and assembler code.
The RFC from May 2015 Y. Nir et al, ChaCha20 and Poly1305 for IETF Protocols
(https://www.rfc-editor.org/rfc/rfc7539) contains a reference to the MIT/Public domain C library https://github.com/floodyberry/poly1305-donna.
I am just porting the C code to Pascal. The 8 bit code works OK (self-test, example, and RFC test vectors).
The port from poly1305-donna-16.h using 16->32 bit multiples and 32 bit additions failed. After some testing I compiled the original source with DJGPP GCC 4.7.3, MS VC 6.0 and BC 3.1 and all three failed too (poly1305 self-test).
Questions: Does this C version (build with -DPOLY1305_16BIT) fail for other compilers too? Is there a known fix available? (The blog of the author Andrew Moon at https://floodyberry.wordpress.com/ is inactive since 6 years)
I can confirm a build failure on a pretty vanilla Fedora 22 system:
% gcc poly1305-donna.c -c -DPOLY1305_16BIT
% gcc example-poly1305.c -o ex poly1305-donna.o -DPOLY1305_16BIT
% ./ex
poly1305 self test: failed
Notice that the test succeeds when I omit -DPOLY1305_16BIT.
Also notice:
% uname -rmp
4.0.8-300.fc22.x86_64 x86_64 x86_64
% gcc --version
gcc (GCC) 5.1.1 20150618 (Red Hat 5.1.1-4)
I suggest you submit a bug report. Andrew has been responsive in the past.
EDIT:
Compiling with clang version 3.5.0 yields the same results as the above gcc test.
I have to start by saying that I am very much a programming noob. I do not understand all the compiler options or nuances of the IDE, not by a longshot. But I am trying to teach myself more about native programming languages. (I'm decent with C#, but that is much easier than C as I am discovering.)
Today, I wrote this small program in C. It is a console/command line program. I used Visual Studio 2012 and my development machine alternates between Windows 7 and 8, 64 bit. To start, what I did was create a new VC++ project, and I chose a Blank Project. Then I created a new app.c file. I also created a *.rc file to give the executable some extra properties like "File Version" and "Company Name" when you browse the file properties in Windows Explorer. Then I went to the properties of the project, chose Configuration Properties -> C/C++ -> Code Generation and I changed Runtime Library to "Multi-threaded (/MT) so that I wouldn't have to distribute the msvcr100.dll file along with my executable.
In the app.c file, I placed the following code:
#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include <WtsApi32.h>
#pragma comment(lib, "WtsApi32.lib")
void main(int argc, char *argv[])
{
char *helpMsg = "blah";
char *hostName, *connState = "";
char *addrFamily = "";
HANDLE hHost = NULL;
...stuff and so forth and so on...
}
Then I built/compiled the program, and the executable works just fine on Windows 7, 8, Server 2008R2, Server 2012, all 64 bit. But when I try to run the program on Server 2003 (and I am guessing WinXP, etc., as well,) I am greeted with the Windows dialog box:
"Foo.exe is not a valid Win32 application."
So my question is, is there something obvious/simple that I am missing that will allow this executable to also work on earlier XP/2003/32bit platforms that I am missing? I do not believe that I am using any 64-bit exclusive features in my program. But I figured that since I did choose "Blank Project" instead of "Win32 Console Application" that I may be missing some setting.
Edit: Here is the dumpbin.exe /headers output when run against my exe:
Microsoft (R) COFF/PE Dumper Version 11.00.50727.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file C:\users\me\Release\foo.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (x86)
5 number of sections
50F604BC time date stamp Tue Jan 15 19:39:08 2013
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
102 characteristics
Executable
32 bit word machine
OPTIONAL HEADER VALUES
10B magic # (PE32)
11.00 linker version
7800 size of code
A200 size of initialized data
0 size of uninitialized data
16A7 entry point (004016A7) _mainCRTStartup
1000 base of code
9000 base of data
400000 image base (00400000 to 00414FFF)
1000 section alignment
200 file alignment
6.00 operating system version
0.00 image version
6.00 subsystem version
0 Win32 version
15000 size of image
400 size of headers
0 checksum
3 subsystem (Windows CUI)
8140 DLL characteristics
Dynamic base
NX compatible
Terminal Server Aware
100000 size of stack reserve
1000 size of stack commit
100000 size of heap reserve
1000 size of heap commit
0 loader flags
10 number of directories
0 [ 0] RVA [size] of Export Directory
D374 [ 3C] RVA [size] of Import Directory
11000 [ 538] RVA [size] of Resource Directory
0 [ 0] RVA [size] of Exception Directory
0 [ 0] RVA [size] of Certificates Directory
12000 [ C04] RVA [size] of Base Relocation Directory
9160 [ 38] RVA [size] of Debug Directory
0 [ 0] RVA [size] of Architecture Directory
0 [ 0] RVA [size] of Global Pointer Directory
0 [ 0] RVA [size] of Thread Storage Directory
CF98 [ 40] RVA [size] of Load Configuration Directory
0 [ 0] RVA [size] of Bound Import Directory
9000 [ 118] RVA [size] of Import Address Table Directory
0 [ 0] RVA [size] of Delay Import Directory
0 [ 0] RVA [size] of COM Descriptor Directory
0 [ 0] RVA [size] of Reserved Directory
SECTION HEADER #1
.text name
7670 virtual size
1000 virtual address (00401000 to 0040866F)
7800 size of raw data
400 file pointer to raw data (00000400 to 00007BFF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
Execute Read
SECTION HEADER #2
.rdata name
49E2 virtual size
9000 virtual address (00409000 to 0040D9E1)
4A00 size of raw data
7C00 file pointer to raw data (00007C00 to 0000C5FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
Read Only
Debug Directories
Time Type Size RVA Pointer
-------- ------ -------- -------- --------
50F604BC cv 61 0000CFE0 BBE0 Format: RSDS, {582D0FF2-59C1-4633-AF2A-E4A4AD6BFA2C}, 1, C:\Users\me\Release\users.pdb
50F604BC feat 10 0000D044 BC44 Counts: Pre-VC++ 11.00=0, C/C++=116, /GS=116, /sdl=0
SECTION HEADER #3
.data name
2C04 virtual size
E000 virtual address (0040E000 to 00410C03)
E00 size of raw data
C600 file pointer to raw data (0000C600 to 0000D3FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0000040 flags
Initialized Data
Read Write
SECTION HEADER #4
.rsrc name
538 virtual size
11000 virtual address (00411000 to 00411537)
600 size of raw data
D400 file pointer to raw data (0000D400 to 0000D9FF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
Read Only
SECTION HEADER #5
.reloc name
235C virtual size
12000 virtual address (00412000 to 0041435B)
2400 size of raw data
DA00 file pointer to raw data (0000DA00 to 0000FDFF)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
42000040 flags
Initialized Data
Discardable
Read Only
Summary
3000 .data
5000 .rdata
3000 .reloc
1000 .rsrc
8000 .text
I have also tried going to Project Properties -> Linker -> System: Minimum Required Version and changing that to 5.00 and 1.00 or whatever, but it has no effect. dumpbin.exe still reports the OS version as 6.00. I have even used editbin.exe /version 5.00 on the exe and no errors were reported... and yet dumpbin.exe still reports 6.00 for the OS version.
VS2012 originally shipped without supporting XP/2003. The updated CRT and runtime support libraries are using too many Windows api functions that are not available on those operating systems. This created quite a stir among its customers, to put it mildly, and they re-engineered the libraries to dynamically bind to these functions and limp along it they are missing. This was made available in Update 1, you'll need to use Project + Properties, General, Platform Toolset = v110_xp to build programs that use those libraries.
Note how it changes a linker setting, the important one, Linker > System > Minimum Required Version = "5.01". Which ensures that the executable file is marked to be compatible with the XP sub-system version. You'll also build against SDK version 7.1, the last one that is still compatible with XP.
When you use the default toolset (v110) then you target sub-system 6.00 and SDK version 8. Version 6.00 was the last major kernel revision, started with Vista.
A brief overview of the new api functions being used to give you a (very rough) idea what is missing in the XP version:
FlsAlloc, FlsFree, FlsGetValue, FlsSetValue : safe thread-local storage
InitializeCriticalSectionEx, CreateSemaphoreEx : safety
SetThreadStackGuarantee : stability
CreateThreadPoolTimer, SetThreadPoolTimer, WaitForThreadPoolTimerCallbacks, CloseThreadPoolTimer : cheaper timers
CreateThreadPoolWait, SetThreadPoolWait, CloseThreadPoolWait : cheaper waits?
FlushProcessWriteBuffers, GetCurrentProcessorNumber, GetLogicalProcessorInformation : threading
FreeLibraryWhenCallbackReturns : stability?
CreateSymbolicLink : functionality
InitOnceExecuteOnce : unknown
SetDefaultDllDirectories : unknown
EnumLocalesEx, CompareStringEx, GetDateFormatEx, GetLocalInfoEx, GetTimeFormatEx, GetUserDefaultLocaleName, IsValidLocaleName, LCMapStringEx : better locale support
I figured it out myself. (But thank you Hans for steering me in the right direction.) For some reason, even with Update 1 and even after setting my toolset to v110_xp, and setting the minimum required version to 5.01 in the Linker options, the resulting dumpbin app.exe /headers still reports a minimum operating system version of 6.0.
So I simply ran
editbin.exe app.exe /SUBSYSTEM:CONSOLE,5.01 /OSVERSION:5.1
And the executable now runs just fine on older operating systems. I'm thinking there still might be a little bit of a bug somewhere in Visual Studio.
The MSVC Team Blog says that when using MSBuild or DEVENV from the command-line with the v110_xp platform toolset, no other changes are necessary. This information is incorrect/incomplete. The /SUBSYSTEM linker argument and associated "Minimum Required Version" must also be set appropriately.
The MSDN documentation for /ENTRY states that, if the /SUBSYSTEM argument is not specified that the SUBSYSTEM and ENTRY POINT are determined automatically. My hunch is that when this happens, the SUBSYSTEM's "Minimum Required Version" argument is also automatically overridden.
The v110_xp toolset automatically specifies the SUBSYSTEM's MRV ("5.1" (WindowsXP)) but not the SUBSYSTEM. As such, the MRV will be overridden, for example, by the linker to "6.0". Running the application will then cause WindowsXP to show the error message stating that the application "is not a valid Win32 application."