ELF Executable Segfaults - binaryfiles

I've been trying to create an ELF executable using libelf, but haven't gotten it running yet. Whenever I try to run it, I just get a segfault. strace outputs:
execve("./test.elf", ["./test.elf"], 0x7ffc28d60660 /* 63 vars */) = -1 EINVAL (Invalid argument)
+++ killed by SIGSEGV +++
readelf gives:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1000
Start of program headers: 64 (bytes into file)
Start of section headers: 152 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 1
Size of section headers: 64 (bytes)
Number of section headers: 3
Section header string table index: 2
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000001000 00000078
0000000000000008 0000000000000000 AX 0 0 1
[ 2] .shstrtab STRTAB 0000000000000000 00000080
0000000000000011 0000000000000000 A 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000078 0x0000000000001000 0x0000000000001000
0x0000000000000008 0x0000000000000008 R E 0x1
Section to Segment mapping:
Segment Sections...
00 .text
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
No version information found in this file.
And here's the hexdump of the file:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 02 00 3e 00 01 00 00 00 00 10 00 00 00 00 00 00 |..>.............|
00000020 40 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 |#...............|
00000030 00 00 00 00 40 00 38 00 01 00 40 00 03 00 02 00 |....#.8...#.....|
00000040 01 00 00 00 05 00 00 00 78 00 00 00 00 00 00 00 |........x.......|
00000050 00 10 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................|
00000060 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................|
00000070 01 00 00 00 00 00 00 00 31 c0 ff c0 b3 2a cd 80 |........1....*..|
00000080 00 2e 74 65 78 74 00 2e 73 68 73 74 72 74 61 62 |..text..shstrtab|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000000d0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
000000e0 06 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 |................|
000000f0 78 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |x...............|
00000100 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 07 00 00 00 03 00 00 00 |................|
00000120 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 80 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 |................|
00000140 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 |........|
00000158
From what I've read and comparing it to working executables, this should work. But it doesn't, and I have no idea why. Any help is appreciated, thanks.

I figured it out! When I was looking at a working executable for reference, I was looking at a PIE, but I was trying to create a non-PIE. I didn't realize the EHDR type needs to be ET_DYN for a PIE. Also, a few of the addresses were wrong.
The new readelf:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1078
Start of program headers: 64 (bytes into file)
Start of section headers: 152 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 1
Size of section headers: 64 (bytes)
Number of section headers: 3
Section header string table index: 2
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000001078 00000078
0000000000000008 0000000000000000 AX 0 0 1
[ 2] .shstrtab STRTAB 0000000000000000 00000080
0000000000000011 0000000000000000 A 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000078 0x0000000000001078 0x0000000000001078
0x0000000000000008 0x0000000000000008 R E 0x1
Section to Segment mapping:
Segment Sections...
00 .text
There is no dynamic section in this file.
There are no relocations in this file.
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
No version information found in this file.
And the new hexdump:
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 3e 00 01 00 00 00 78 10 00 00 00 00 00 00 |..>.....x.......|
00000020 40 00 00 00 00 00 00 00 98 00 00 00 00 00 00 00 |#...............|
00000030 00 00 00 00 40 00 38 00 01 00 40 00 03 00 02 00 |....#.8...#.....|
00000040 01 00 00 00 05 00 00 00 78 00 00 00 00 00 00 00 |........x.......|
00000050 78 10 00 00 00 00 00 00 78 10 00 00 00 00 00 00 |x.......x.......|
00000060 08 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |................|
00000070 01 00 00 00 00 00 00 00 31 c0 ff c0 b3 2a cd 80 |........1....*..|
00000080 00 2e 74 65 78 74 00 2e 73 68 73 74 72 74 61 62 |..text..shstrtab|
00000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
*
000000d0 00 00 00 00 00 00 00 00 01 00 00 00 01 00 00 00 |................|
000000e0 06 00 00 00 00 00 00 00 78 10 00 00 00 00 00 00 |........x.......|
000000f0 78 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 |x...............|
00000100 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000110 00 00 00 00 00 00 00 00 07 00 00 00 03 00 00 00 |................|
00000120 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000130 80 00 00 00 00 00 00 00 11 00 00 00 00 00 00 00 |................|
00000140 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 |................|
00000150 00 00 00 00 00 00 00 00 |........|
00000158

Related

Lattice ECP5 UART, no signal on terminal emulator

I followed this tutorial to the letter, but I'll to explain in detail what steps I took exactly. I have an ECP5-evaluation 85k board.
I soldered bridges on R34/R35 (RX/TX) and R21 (connects LED D1 to RXD)
I used my windows installation to run the latest version of FT_PROG. In FT_PROG I went to FT_EEPROM -> Hardware Specific -> Port B -> Hardware and set it to RS232 and hit program. It completed succesfully according to the software.
Then I forwarded the USB port to my virtual box linux machine. It recognizes the board and I can succesfully run verilog files on it.
I ran ./raw_serial.sh to upload raw_serial.v to my board which is supposed to repeatedly print A to the serial monitor.
I then opened minicom on /dev/ttyUSB1 and it recognizes the device, baudrate is set correctly.
I then tried to use cu as follows: sudo chmod 666 /dev/ttyUSB1 && sudo cu -l /dev/ttyUSB2 -s 115200. It opens a terminal and says it is connected.
Led D1 is lighting up and both terminal programs indicate that the connection is succesful (I tried one of them at a time of course). Nothing is printed to the screen. When I use minicom and reupload raw_serial.v some <?> signs are printed to the screen but that's it. I tried turning echo on and off but nothing seems to work.
The following worked for me and it will probably work for others too. I'm assuming you're using openocd.
Do not use FT_PROG in windows, it doesn't seem to actually flash the FTDI chip. However, it lets you read back the hex dump that was supposed to be flashed to the chip. The hex dump for the unchanged EEPROM as it comes out of the box is as follows:
00000000 01 08 03 04 10 60 00 07 C0 FA 08 00 11 11 9A 10 .....`..Àú....š.
00000010 AA 3C E6 12 00 00 00 00 56 00 00 00 00 00 00 00 ª<æ.....V.......
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050 00 00 00 00 00 00 02 03 00 00 00 00 00 00 00 00 ................
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090 00 00 00 00 00 00 00 00 00 00 10 03 4C 00 61 00 ............L.a.
000000A0 74 00 74 00 69 00 63 00 65 00 3C 03 4C 00 61 00 t.t.i.c.e.<.L.a.
000000B0 74 00 74 00 69 00 63 00 65 00 20 00 45 00 43 00 t.t.i.c.e. .E.C.
000000C0 50 00 35 00 20 00 45 00 76 00 61 00 6C 00 75 00 P.5. .E.v.a.l.u.
000000D0 61 00 74 00 69 00 6F 00 6E 00 20 00 42 00 6F 00 a.t.i.o.n. .B.o.
000000E0 61 00 72 00 64 00 12 03 46 00 54 00 32 00 55 00 a.r.d...F.T.2.U.
000000F0 59 00 54 00 4A 00 56 00 00 00 00 00 00 00 FC 27 Y.T.J.V.......ü'
I just post this here for future reference, we're not going to use the stock eeprom.
We need to flash the eeprom to RS232-HS mode. To do so, we must first change the hex dump of the eeprom accordingly. To put channel B in RS232-HS mode we need to change the last column of the last row from ' to |. Create a hex file called eeprom_RS232.bin with the following contents:
00000000 01 08 03 04 10 60 00 07 C0 FA 08 00 11 11 9A 10 .....`..Àú....š.
00000010 AA 3C E6 12 00 00 00 00 56 00 00 00 00 00 00 00 ª<æ.....V.......
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000050 00 00 00 00 00 00 02 03 00 00 00 00 00 00 00 00 ................
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000090 00 00 00 00 00 00 00 00 00 00 10 03 4C 00 61 00 ............L.a.
000000A0 74 00 74 00 69 00 63 00 65 00 3C 03 4C 00 61 00 t.t.i.c.e.<.L.a.
000000B0 74 00 74 00 69 00 63 00 65 00 20 00 45 00 43 00 t.t.i.c.e. .E.C.
000000C0 50 00 35 00 20 00 45 00 76 00 61 00 6C 00 75 00 P.5. .E.v.a.l.u.
000000D0 61 00 74 00 69 00 6F 00 6E 00 20 00 42 00 6F 00 a.t.i.o.n. .B.o.
000000E0 61 00 72 00 64 00 12 03 46 00 54 00 32 00 55 00 a.r.d...F.T.2.U.
000000F0 59 00 54 00 4A 00 56 00 00 00 00 00 00 00 FC 27 Y.T.J.V.......ü|
Now, we need to flash this eeprom to our ECP5 using Anton's method. To do this, first create a file ftdi_RS232.conf with the following contents:
vendor_id=0x403
product_id=0x6010
filename="eeprom_RS232.bin"
flash_raw=true
With the following command we can flash to our ECP5: ftdi_eeprom --flash-eeprom ftdi_RS232.conf. Should we ever want to revert back to the stock eeprom, we can easily repeat this method with the hex dump given in step 1.
Now it's time to flash the verilog file. However, the device description of the ECP5 has changed from Lattice ECP5 Evaluation Board to Dual RS232-HS. We need to tell openocd to look for that specific device. Start by creating a file ecp5.cfg with the following contents:
# this supports ECP5 Evaluation Board
interface ftdi
ftdi_device_desc "Dual RS232-HS"
ftdi_vid_pid 0x0403 0x6010
# channel 1 does not have any functionality
ftdi_channel 0
# just TCK TDI TDO TMS, no reset
ftdi_layout_init 0xfff8 0xfffb
reset_config none
# default speed
adapter_khz 5000
# ECP5 device - LFE5UM5G-85F
jtag newtap ecp5 tap -irlen 8 -expected-id 0x81113043
Then, create your svf file as you usually do and flash it with the following command:
sudo --preserve-env=PATH env openocd -f ./ecp5.cfg -c "transport select jtag; init; svf raw_serial.svf; exit"
Finally, we can open a terminal to read the serial output of the ECP5. Personally, I like to use minicom: sudo chmod 666 /dev/ttyUSB0 && minicom -D /dev/ttyUSB0.
One more problem with the raw_serial.v example was that it doesn't use a baudrate of 115200 as the readme suggests but 19200. The clock that is connected to the FTDI chip runs at 12 MHz. If you want a baudrate of 115200 you need to send a bit every 12,000,000 / 115,200 ~= 104 ticks. This means you need to change line 14 to if (counter == 104) begin.

Wider hexdump output

I'm a big fan of the default formatting of the hd command. For example:
$ head -c128 /bin/bash |hd
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............|
00000010 03 00 3e 00 01 00 00 00 30 f6 02 00 00 00 00 00 |..>.....0.......|
00000020 40 00 00 00 00 00 00 00 48 ce 11 00 00 00 00 00 |#.......H.......|
00000030 00 00 00 00 40 00 38 00 0b 00 40 00 1d 00 1c 00 |....#.8...#.....|
00000040 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00 |........#.......|
00000050 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |#.......#.......|
00000060 68 02 00 00 00 00 00 00 68 02 00 00 00 00 00 00 |h.......h.......|
00000070 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00 |................|
00000080
I'm looking for a hexdump command that does the same thing but is double-wide. Output should look something like:
$ head -c128 /bin/bash |2hd
00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 03 00 3e 00 01 00 00 00 30 f6 02 00 00 00 00 00 |.ELF............| |..>.....0.......|
00000020 40 00 00 00 00 00 00 00 48 ce 11 00 00 00 00 00 00 00 00 00 40 00 38 00 0b 00 40 00 1d 00 1c 00 |#.......H.......| |....#.8...#.....|
00000040 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |........#.......| |#.......#.......|
00000060 68 02 00 00 00 00 00 00 68 02 00 00 00 00 00 00 08 00 00 00 00 00 00 00 03 00 00 00 04 00 00 00 |h.......h.......| |................|
00000080
So far, I've got this. It does not line up properly.
2hd() {
local poe='" " 8/1 "%02x "' # pieces of eight, heh
hexdump -e '"%07.7_Ax\n"' \
-e '"%07.7_ax" '"$poe $poe $poe $poe"' " |" 32/1 "%_p" "|\n"' "$#"
}
$ head -c128 /bin/bash |2hd
0000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 03 00 3e 00 01 00 00 00 30 f6 02 00 00 00 00 00 |#.......H...........#.8...#.....|
0000040 06 00 00 00 04 00 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 |h.......h.......................|
0000080 a8 02 00 00 00 00 00 00 a8 02 00 00 00 00 00 00 a8 02 00 00 00 00 00 00 1c 00 00 00 00 00 00 00 |................................|
00000c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 98 cd 02 00 00 00 00 00 98 cd 02 00 00 00 00 00 |................................|
0000100
(I haven't decided whether or not I want the right-side display to be in one part or two.)
I'm hoping to do this entirely within a single reference to hexdump. It'd help to know what the hexdump command to get the 16-col hd output would look like too. (The docs I can find are not helpful at this.)
I think you may just need to split the second -e:
2hd() {
local poe='" " 8/1 "%02x "'
hexdump -e '"%07.7_Ax\n"' \
-e '"%07.7_ax" '"$poe $poe $poe $poe" \
-e ' " |" 32/1 "%_p" "|\n"' "$#"
}
Multiple -e each work on the same input. In your original, the %_p applies to the input after the %x because it is in the same -e.
busybox hexdump source defines -C as:
bb_dump_add(dumper, "\"%08.8_Ax\n\""); // final address line after dump
//------------------- "address " 8 * "xx " " " 8 * "xx "
bb_dump_add(dumper, "\"%08.8_ax \"8/1 \"%02x \"\" \"8/1 \"%02x \"");
//------------------- " |ASCII...........|\n"
bb_dump_add(dumper, "\" |\"16/1 \"%_p\"\"|\n\"");
so that means you can implement hd as:
hexdump -e "\"%08.8_Ax\n\"" -e "\"%08.8_ax \"8/1 \"%02x \"\" \"8/1 \"%02x \"" \
-e "\" |\"16/1 \"%_p\"\"|\n\""

What format are GCC's object files in?

I assembled an assembly file in GCC under Windows like so:
as main.s -o main.o
And now I have the following object file:
4C 01 03 00 00 00 00 00 90 00 00 00 08 00 00 00
00 00 05 01 2E 74 65 78 74 00 00 00 00 00 00 00
00 00 00 00 04 00 00 00 8C 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 20 00 30 60 2E 64 61 74
61 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
40 00 30 C0 2E 62 73 73 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 80 00 30 C0 C3 90 90 90
2E 66 69 6C 65 00 00 00 00 00 00 00 FE FF 00 00
67 01 66 61 6B 65 00 00 00 00 00 00 00 00 00 00
00 00 00 00 2E 74 65 78 74 00 00 00 00 00 00 00
01 00 00 00 03 01 01 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 2E 64 61 74 61 00 00 00
00 00 00 00 02 00 00 00 03 01 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 2E 62 73 73
00 00 00 00 00 00 00 00 03 00 00 00 03 01 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
04 00 00 00
I'd like to look inside this file to try and understand how object files are put together. Where can I find a format specification for whatever format this file is?

What are the differences between a Windows bitmap and DIBSection?

I'm loading a DIBSection from a file with the following:
HBITMAP bmpIn = (HBITMAP) LoadImage(NULL, _T("c:\\Temp\\Temp.bmp"), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
Empirically I've discovered the following differences between the loaded bitmap and the bitmaps that I've used in the past, but I can't find any documentation stating that there should be a difference.
The lines are ordered in memory top down rather than bottom up. I've verified that the .bmp file itself is ordered bottom up.
The row padding is to a multiple of 2 bytes rather than 4.
I've also discovered a documented difference when you use CreateDIBSection to create a DIBSection from scratch.
The DIBSECTION.dsHandle and BITMAP.bmBits values returned by GetObject will be NULL.
Where's the documentation for the first two differences, and am I missing anything? This is with Windows 7 but I can't imagine it would be different for other versions of Windows.
Edit: Some additional details. Here's a hex dump of temp.bmp; it's a 7x7 image with a white stripe down the right side and blue values incrementing along the left (0x10,0x20,etc.). You can see that the bottom line (00,00,70) is first and that there's 3 bytes of padding.
00: 42 4d de 00 00 00 00 00 00 00 36 00 00 00 28 00
10: 00 00 07 00 00 00 07 00 00 00 01 00 18 00 00 00
20: 00 00 a8 00 00 00 00 00 00 00 00 00 00 00 00 00
30: 00 00 00 00 00 00 70 00 00 00 00 00 00 00 00 00
40: 00 00 00 00 00 00 00 00 ff ff ff 00 00 00 60 00
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
60: ff ff ff 00 00 00 50 00 00 00 00 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 ff ff ff 00 00 00 40 00
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: ff ff ff 00 00 00 30 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 ff ff ff 00 00 00 20 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c0: ff ff ff 00 00 00 10 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 00 00 00 00 ff ff ff 00 00 00
Here's a sample program to read the .bmp file and write out the contents. I've removed error checking for brevity.
int _tmain(int argc, _TCHAR* argv[])
{
HBITMAP bmpIn = (HBITMAP) LoadImage(NULL, argv[1], IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
FILE * out = _tfopen(argv[2], _T("wb"));
DIBSECTION obj = {0};
GetObject(bmpIn, sizeof(obj), &obj);
cout << "dsBm.bmHeight = " << obj.dsBm.bmHeight << endl;
cout << "dsBmih.biHeight = " << obj.dsBmih.biHeight << endl;
cout << "sizeof(DIBSECTION) = " << sizeof(DIBSECTION) << endl;
fwrite(&obj, sizeof(DIBSECTION), 1, out);
int stride = (((obj.dsBmih.biWidth * obj.dsBmih.biBitCount) + 15) / 16) * 2;
int bytecount = abs(obj.dsBmih.biHeight) * stride;
vector<BYTE> bits(bytecount);
GetBitmapBits(bmpIn, bytecount, &bits[0]);
fwrite(&bits[0], 1, bytecount, out);
fclose(out);
return 0;
}
And here's the output from the above program along with a hex dump of the file produced:
dsBm.bmHeight = 7
dsBmih.biHeight = 7
sizeof(DIBSECTION) = 84
00: 00 00 00 00 07 00 00 00 07 00 00 00 18 00 00 00
10: 01 00 18 00 00 00 11 00 28 00 00 00 07 00 00 00
20: 07 00 00 00 01 00 18 00 00 00 00 00 a8 00 00 00
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
50: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00
60: 00 00 00 00 00 00 ff ff ff 00 20 00 00 00 00 00
70: 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff 00
80: 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
90: 00 00 ff ff ff 00 40 00 00 00 00 00 00 00 00 00
a0: 00 00 00 00 00 00 00 00 ff ff ff 00 50 00 00 00
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff
c0: ff 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00
d0: 00 00 00 00 ff ff ff 00 70 00 00 00 00 00 00 00
e0: 00 00 00 00 00 00 00 00 00 00 ff ff ff 00
Call GetDIBits instead of GetBitmapBits. The docs for GetBitmapBits (here) indicate that this is returning data for a device-dependent bitmap, whereas you have a device-independent bitmap. They also indicate that this call shouldn't be used and is just there for 16-bit compatibility. So, using GetDIBits should do the trick.

What is RIDI_PREPARSEDDATA in GetRawInputDeviceInfo?

Windows API function GetRawInputDeviceInfo has a parameter uiCommand. One of the options is RIDI_PREPARSEDDATA. It says "pData points to the previously parsed data".
I don't get what previously parsed data they are referring to. Is it the data that was last sent with WM_INPUT? Or is it data that was returned by any of the functions? Or something else? Also in what format is that data?
Preparsed data is report descriptor data associated with a top-level collection. User-mode applications or kernel-mode drivers use preparsed data to extract information about specific HID controls without having to obtain and interpret a device's entire report descriptor.
MSDN Link
"Also in what format is that data?"
Today I looked into GetRawInputDeviceInfo(), including the RIDI_PREPARSEDDATA data. Here's the output of the program when I test my XBOX controller. Everything except for displayable characters are in hex, and the hex for the displayable characters are given in parentheses after the displayable character.
getting device info...
Preparing 5 device lists...
Getting 5 devices...
index: type| location
0: HID| 0x01FB035F
1: Keyboard| 0x0001003F
2: Keyboard| 0x000B003D
3: Mouse| 0x0001003B
4: Mouse| 0x000B0039
Which would you like more info about?__
Pointer: 0x01FB035F
Type: HID
Name: \\?\HID#VID_0E6F&PID_0401&IG_00#7&2c93b906&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
Vendor ID: 0x00000e6f
Product ID: 0x00000401
Version Number: 0x00000000
Usage Page: 0x0001
Usage: 0x0005
DATA: (940 bytes)
H(0x48) i(0x69) d(0x64) P(0x50)
(0x20) K(0x4b) D(0x44) R(0x52)
05 00 01 00
00 00 00 00
00 00 07 00
07 00 0f 00
07 00 00 00
07 00 00 00
07 00 00 00
07 00 00 00
d8 02 04 00
01 00 00 00
10 00 01 00
03 00 10 00
02 00 00 00
05 00 01 00
01 00 00 00
08 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
1(0x31) 00 1(0x31) 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
ff ff ff ff
00 00 00 00
ff ff ff ff
00 00 00 00
00 00 00 00
01 00 00 00
10 00 01 00
01 00 10 00
02 00 00 00
03 00 01 00
01 00 00 00
08 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
0(0x30) 00 0(0x30) 00
00 00 00 00
00 00 00 00
01 00 01 00
00 00 00 00
00 00 00 00
ff ff ff ff
00 00 00 00
ff ff ff ff
00 00 00 00
00 00 00 00
01 00 00 00
10 00 01 00
07 00 10 00
02 00 00 00
09 00 02 00
01 00 00 00
08 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
4(0x34) 00 4(0x34) 00
00 00 00 00
00 00 00 00
02 00 02 00
00 00 00 00
00 00 00 00
ff ff ff ff
00 00 00 00
ff ff ff ff
00 00 00 00
00 00 00 00
01 00 00 00
10 00 01 00
05 00 10 00
02 00 00 00
07 00 02 00
01 00 00 00
08 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
3(0x33) 00 3(0x33) 00
00 00 00 00
00 00 00 00
03 00 03 00
00 00 00 00
00 00 00 00
ff ff ff ff
00 00 00 00
ff ff ff ff
00 00 00 00
00 00 00 00
01 00 00 00
10 00 01 00
09 00 10 00
02 00 00 00
0b 00 03 00
01 00 00 00
08 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
2(0x32) 00 2(0x32) 00
00 00 00 00
00 00 00 00
04 00 04 00
00 00 00 00
00 00 00 00
ff ff ff ff
00 00 00 00
ff ff ff ff
00 00 00 00
00 00 00 00
09 00 00 00
01 00 0a 00
0b 00 0a 00
02 00 00 00
0d 00 00 00
01 00 05 00
1c 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
01 00 0a 00
00 00 00 00
00 00 00 00
05 00 0e 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
01 00 00 02
04 00 01 00
0c 00 04 00
B(0x42) 00 00 00
0d 00 00 00
01 00 05 00
08 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
9(0x39) 00 9(0x39) 00
00 00 00 00
00 00 00 00
0f 00 0f 00
01 00 00 00
01 00 00 00
08 00 00 00
00 00 00 00
;(0x3b) 10 00 00
0e 00 00 00
00 00 00 00
05 00 01 00
00 00 03 00
00 00 03 00
01 00 00 00
00 00 01 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 01 00
00 00 00 00
01 00 00 00
00 00 00 00
00 00 01 00
00 00 00 00
02 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
end of data.Press any key to continue . . .
Notice the HidP KDR at the beginning. Other than that it looks like gibberish. The program formatted it nicely into four-octet words, but it looks like it will not display properly here without extra effort from me. Yes, it is meant to display on a command line, and no, I do not want to get rid of the result of system("pause").

Resources