In a compressed PE must the virtual size of the data section match the raw size? - c

In working with a compressed PE (Windows console EXE) that has a file alignment and section alignment of 4 bytes, I notice that if virtual size and raw size of the sections match, then the program loads, but if virtual size of the data section, the last section, does not match then Windows refuses to load it, even though by the specification you should be able to have a virtual size larger than a raw size.
Is this some kind of hidden constraint on compressed PEs?
I have pasted a dumpbin /headers of the exe below:
Microsoft (R) COFF/PE Dumper Version 10.00.30319.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file ba42x.exe
PE signature found
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (x86)
2 number of sections
50AABC14 time date stamp Mon Nov 19 18:09:08 2012
0 file pointer to symbol table
0 number of symbols
60 size of optional header
10F characteristics
Relocations stripped
Executable
Line numbers stripped
Symbols stripped
32 bit word machine
OPTIONAL HEADER VALUES
10B magic # (PE32)
2.03 linker version
BD0 size of code
5000 size of initialized data
0 size of uninitialized data
CC entry point (004000CC)
CC base of code
C9C base of data
400000 image base (00400000 to 00403FFF)
4 section alignment
4 file alignment
4.00 operating system version
0.00 image version
4.00 subsystem version
0 Win32 version
4000 size of image
CC size of headers
0 checksum
3 subsystem (Windows CUI)
0 DLL characteristics
10000 size of stack reserve
1000 size of stack commit
0 size of heap reserve
0 size of heap commit
0 loader flags
0 number of directories
SECTION HEADER #1
.text name
BD0 virtual size
CC virtual address (004000CC to 00400C9B)
BD0 size of raw data
CC file pointer to raw data (000000CC to 00000C9B)
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
E0000020 flags
Code
Execute Read Write
SECTION HEADER #2
.data name
3102 virtual size
C9C virtual address (00400C9C to 00403D9D)
3102 size of raw data
C9C file pointer to raw data (00000C9C to 00003D9D)
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
Summary
3104 .data
BD0 .text
For example if you change the virtual size of the above .data section to 3106 the program will not load, even though the size of initialized data (0x5000) is more than enough to accomodate the additional memory.

No, there are not special constraints related to compressed images, since as long as your image is PE compliant, the loader does not care about the compression. Compression is handled by the stub, not the loader.
Can you provide your image for further analysis?
Just by looking at the output of dumpbin, the image looks unusual..There are no directory at all, pretty strange. It looks like the issue with the loader is not directly related to the alignement, but malformation of the image file. Did you try to have a look at your image file using other PE tools (e.g. PeStudio, CFF Explorer..?)

Related

where is uboot environment variables stored in emmc?

I'm trying to understand where uboot stores the environment variables in emmc. I have the following set in the uboot config file -
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_MMC_ENV_DEV=2
CONFIG_SYS_MMC_ENV_PART=0
CONFIG_ENV_SIZE=0x4000
CONFIG_ENV_OFFSET=0x400000
CONFIG_ENV_SECT_SIZE=0x10000
uboot is able to save the env variables in emmc and I can read them from Linux. Variables set from Linux are also readable in uboot. I fail to understand which partition has the environment variables?
Output lsblk from Linux -
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
mtdblock0 31:0 0 16M 0 disk
mmcblk2 179:0 0 7.3G 0 disk
|-mmcblk2p1 179:1 0 83.2M 0 part /run/media/mmcblk2p1
|-mmcblk2p2 179:2 0 1.7G 0 part /
|-mmcblk2p3 179:3 0 83.2M 0 part /run/media/mmcblk2p3
|-mmcblk2p4 179:4 0 1K 0 part
|-mmcblk2p5 179:5 0 1.7G 0 part /run/media/mmcblk2p5
`-mmcblk2p6 179:6 0 1G 0 part /run/media/mmcblk2p6
mmcblk2boot0 179:32 0 4M 1 disk
mmcblk2boot1 179:64 0 4M 1 disk
mmcblk2boot0 is where uboot is located which is 4MB in size, considering the environment is saved at an offset of 0x400000 in mmcblk2 device, it should be located just after mmcblk2boot0 which points to the parition mmcblk2boot1, but if I dump the strings "strings /dev/mmcblk2boot1", I get nothing.
I have provided a file /etc/fw_config which is used by fw_printenv and fw_saveenv, this file contains "/dev/mmcblk2 0x400000 0x10000". All the settings point to the fact that uboot environment is located at an offset of 0x400000 in mmcblk2 device. Any pointers on which partition listed in output of lsblk holds the uboot environment variables..?
Thanks,
Vinay
The confusing thing here is that CONFIG_SYS_MMC_ENV_PART does not refer to sofware partitions, such as /dev/mmcblk2p1 that you see under Linux, but rather hardware partitions such as /dev/mmcblk2 (partition 0) or /dev/mmcblk2boot0 (partition 1).

What does the "Rva+Base" mean in a MSVC linker generated map file?

I compiled a C program and linked with the Microsoft linker link.exe.
The linker generated a *.map file. Below are some snippets:
Start Length Name Class
0001:00000000 00000180H .text CODE
0001:00000180 00049158H .text$mn CODE
0002:00000000 000090c4H .rdata DATA
0002:000090c4 00000130H .rdata$zzzdbg DATA
0003:00000000 00002060H .data DATA
0003:00002060 00001370H .bss DATA
0004:00000000 00002790H .pdata DATA
0005:00000000 000003e4H .xdata DATA
Address Publics by Value Rva+Base Lib:Object
0002:000000c0 _gVar 0000000000049660 MyLib:File1.obj
My understanding is:
The .rdata section has the index 0002 with the length 0x90c4.
The _gVar global variable has the Address like 0002:000000c0, so it lives in the .rdata seciton with the section offset 0xc0.
The base address of the .rdata section is decided by the loader at runtime.
My confusion is about the Rva+Base column.
I checked the binary file at offset 0x49660. It contains exactly the value I assigned for the _gVar. So it seems Rva+Base is the offset from the beginning of the file.
But I think the Rva + Base should equal to absolute virtual address, which can only be decided by the loader at runtime.
How could it be the file offset? Or an unfortunate typo in the column name?
(Btw, I searched a lot for an authoritative reference about the .map file generated by link.exe. But no luck so far. If anyone can share some resource, it will be deeply appreciated.)
ADD 1 - 5:31 PM 4/8/2019
Based on 500 - Internal Server Error's comment, I use CFF Explorer to verify the PE sections. It looks like below:
According to the PE sepc:
Virtual Address: For executable images, the address of the first byte of the section relative to the image base when the section is
loaded into memory.
Raw Address/PointerToRawData: The file pointer to the first page of the section within the COFF file.
These 2 columns have the same data in my scenario.
And in the PE Optional Header, the ImageBase is 0 (this is because of my link flag /BASE:0):
When linker generated the .map file, it has no knowledge about where the image will be loaded at runtime. So it has to use the ImageBase=0 to calculate the Rva+Base column.
The _gVar's absolute virtual address = ImageBase(0) + .rdata Virtual Address(0x495A0) + offset into .rdata (0xc0) = 0x49660
In my case,
The Virtual Address column has the same value as Raw Address column.
And ImageBase = 0 has the same effect of file beginning offset = 0
So the final absolute virtual address equals the file offset, but this is only specific to my scenario.

Is there a way to calculate I/O and memory of current process in C?

If I use
/usr/bin/time -f"%e,%P,%M,%I,%O"
I get (for the last three placeholders) the memory the process used, and if there was some input and output during it.
Obviously, it's easy to get %e or something like it using sys/time.h, but is there a way to get %M, %I and %O programmatically?
You could read and parse the files in the /proc filesystem. /proc/self refers to the process accessing the /proc filesystem.
/proc/self/statm contains information about memory usage, measured in pages. Sample output:
% cat /proc/self/statm
1115 82 63 12 0 79 0
Fields are size resident share text lib data dt; see the proc manual page for some additional details.
/proc/self/io contains the I/O for the current process. Sample output:
% cat /proc/self/io
rchar: 2012
wchar: 0
syscr: 6
syscw: 0
read_bytes: 0
write_bytes: 0
cancelled_write_bytes: 0
Unfortunately, io isn't documented in the proc manual page (at least on my Debian system). I had too check the iotop source code to see how it obtained the per process I/O information.

C Program Written in VS2012 Works w/ Win7/8/2008R2/2012, but not 2003/XP/32bit?

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."

Why does arm-none-eabi-size report the .data section to be 0 even though I am using initialized RAM?

I am a bit confused by the results I am getting when I use my toolchain's (Yagarto and codesourcery) size utility. it is reporting that I am using 0 bytes in the data section. see below
$ arm-none-eabi-size.exe rest-server-example.crazy-horse.elf
text data bss dec hex filename
79364 0 34288 113652 1bbf4 rest-server-example.crazy-horse.elf
I know my code is using and initializing static RAM variables to values other than 0.
interestingly enough when I pass the size tool directly some of the object files that are getting linked I see .data section being reported
example:
text data bss dec hex filename
1648 0 20 1668 684 obj_crazy-horse/uip-nd6.o
200 12 2652 2864 b30 obj_crazy-horse/uip-packetqueue.o
12 0 0 12 c obj_crazy-horse/uip-split.o
1816 24 48 1888 760 obj_crazy-horse/usb-core.o
284 0 0 284 11c obj_crazy-horse/usb-interrupt.o
2064 20 188 2272 8e0 obj_crazy-horse/xmac.o
Why would the elf file report 0 for the .data section when the object files that make it are reporting non-zero values?
FYI I am working on embedded software for a AT91SAM7x256 Micro
edit:
adding the CFLAGS and LDFLAGS
CFLAGS += -O -DRUN_AS_SYSTEM -DROM_RUN -ffunction-sections
LDFLAGS += -L $(CPU_DIRECTORY) -T $(LINKERSCRIPT) -nostartfiles -Wl,-Map,$(TARGET).map
edit #2:
from the object dump we can clearly see that the .data section has data assigned to it but the size utility is not picking it up for some reason
objdump link
All I am looking for is to get an exact usage of my RAM I am not trying to figure out whether one of my variables was optimized out.
edit 3:
more information showing that the size utility does see something in the .data section
$ arm-none-eabi-size.exe -A -t -x rest-server-example.crazy-horse.elf
rest-server-example.crazy-horse.elf :
section size addr
.vectrom 0x34 0x100000
.text 0x10fc8 0x100038
.rodata 0x149c 0x111000
.ARM.extab 0x30 0x11249c
.ARM.exidx 0xe0 0x1124cc
.data 0x1028 0x200000
.bss 0x7bec 0x201028
.stack 0xa08 0x20f5f8
.ARM.attributes 0x32 0x0
.comment 0x11 0x0
.debug_aranges 0xc68 0x0
.debug_info 0x2b87e 0x0
.debug_abbrev 0x960b 0x0
.debug_line 0x9bcb 0x0
.debug_frame 0x4918 0x0
.debug_str 0x831d 0x0
.debug_loc 0x13fad 0x0
.debug_ranges 0x620 0x0
Total 0x7c4c5
My interpretation would be that the linker script creates a single loadable section, which contains the initial values of the data section and a piece of startup code that copies the data to the uninitialized data section.
This is necessary if you want to have a single image file that can be run from read-only memory, as there is no ELF loader in front then that would perform that copy for you.
Normally, this is only done in the section to segment mapping (i.e. the output sections are arranged in the linker script using the > section placement command) rather than by mapping the input section twice, but that is certainly possible as well.
The usage numbers are quite accurate: the text size is the amount of Flash space needed, the BSS size is the amount of RAM needed. Initialized data is counted twice, once for the initial data in Flash, and once for the modifiable data in RAM.
Your .data section have the CODE attribute set, and this confuses "arm-none-eabi-size". The size of the .data section is incorrectly added to the total text size instead of the data size.
My guess is that you have some code that is stored in flash but is copied to ram at run time such as a fast interrupt handler or flash reprogramming that must run from RAM. This will set the CODE attribute for the data segment, and "size" believes that all of .data is text.

Resources