Printf raw data to a fixed length hex output - c

I have a struct, well pointer to a struct, and I wish to printf the first n bytes as a long hex number, or as a string of hex bytes.
Essentially I need the printf equivalent of gdb's examine memory command, x/nxb .
If possible I would like to still use printf as the program's logger function just variant of it. Even better if I can do so without looping through the data.

Just took Eric Postpischil's advice and cooked up the following :
struct mystruc
{
int a;
char b;
float c;
};
int main(int argc, char** argv)
{
struct mystruc structVar={5,'a',3.9};
struct mystruc* strucPtr=&structVar;
unsigned char* charPtr=(unsigned char*)strucPtr;
int i;
printf("structure size : %zu bytes\n",sizeof(struct mystruc));
for(i=0;i<sizeof(struct mystruc);i++)
printf("%02x ",charPtr[i]);
return 0;
}
It will print the bytes as fas as the structure stretches.
Update : Thanks for the insight Eric :) I have updated the code.

Try this. Say you have pointer to struct in pstruct.
unsigned long long *aslong = (unsigned long long *)pstruct;
printf("%08x%08x%08x%08x%08x%08x%08x%08x",
aslong[0],
aslong[1],
aslong[2],
aslong[3],
aslong[4],
aslong[5],
aslong[6],
aslong[7],
);
As Eric points out, this might print the bytes out-of-order. So it's either this, or using unsigned char * and (having a printf with 64 arguments or using a loop).

Related

printf char as hex in c

I expect ouput something like \9b\d9\c0... from code below, but I'm getting \ffffff9b\ffffffd9\ffffffc0\ffffff9d\53\ffffffa9\fffffff4\49\ffffffb0\ffff
ffef\ffffffd9\ffffffaa\61\fffffff7\54\fffffffb. I added explicit casting to char, but it has no effect. What's going on here?
typdef struct PT {
// ... omitted
char GUID[16];
} PT;
PT *pt;
// ... omitted
int i;
for(i=0;i<16;i++) {
printf("\\%02x", (char) pt->GUID[i]);
}
Edit: only casting to (unsigned char) worked for me. Compiler spits warnings on me when using %02hhx (gcc -Wall). (unsigned int) had no effect.
The reason why this is happening is that chars on your system are signed. When you pass them to functions with variable number of arguments, such as printf (outside of fixed-argument portion of the signature) chars get converted to int, and they get sign-extended in the process.
To fix this, cast the value to unsigned char:
printf("\\%02hhx", (unsigned char) pt->GUID[i]);
Demo.
Use:
printf("\%02hhx", pt->GUID[i]);
Because printf() is a variadic function, its arguments are promoted to int. The hh modifier tells printf() that the type of the corresponding value is unsigned char and not int.
Cast to unsigned char instead, to avoid a leading 1 bit being interpreted as a negative value.
I noticed that you were getting the F's when the number was larger than 99x.
I wrote this to test it out and discovered the hh prefix at http://www.cplusplus.com/reference/cstdio/printf/
#include "stdio.h"
char GUID[16];
int main() {
int i;
for(i=0;i<16;i++) {
GUID[i]=i*i;
}
for(i=0;i<16;i++) {
printf("\\%02.2hhx\n", GUID[i]);
}
return 0;
}
Use a small own implementation to solve this problem on all platforms:
char hex[] = "0123456789abcdef";
void printHex(unsigned char byte) {
printf("%c%c", hex[byte>>4], hex[byte&0xf]);
}

Function working fine in stand alone mode but not in a larger program

I have a c program with multiple headers and source files. On running, the program gives segmentation fault. On using "up" and "print variable" commands, i figured that the function "busntoint()" is not working properly.
I have following functions for converting a string of length n from binary to decimal:
unsigned int busntoint(int n, busn bus)
{
unsigned int value = 0;
int i;
for (i=0; i < n; i++) {
if (bus[i] == '1') value += (unsigned int)pow(2,(n-1-i));
}
return value;
}
unsigned int bus2toint(bus2 bus)
{
return busntoint(2, bus);
}
unsigned int bus32toint(bus32 bus)
{
return busntoint(32, bus);
}
I then wrote another program to check the working of these functions. It works just fine and gives the correct and expected output. I dunno why it is not working properly in the "bigger" program.
If it's useful, following is the definition of variables:
typedef char bus2[3];
typedef char bus3[4];
typedef char bus5[6];
typedef char bus6[7];
typedef char bus8[9];
typedef char bus16[17];
typedef char bus32[33];
The usage of the function in the "bigger" program is as follows:
int LoadMemory(char * binfilename, bus8 memory[4096])
{
//some code
int addr = bus32toint(line);
setbit8(memory[addr], &line[33]);
//some code
}
p addr in gdb gives garbage value, leading to segmentation fault in memory[addr].
Your first problem probably lies in your abuse of pow to compute powers of two and the possible overflow that your computation may encounter.
The correct way of computing integer powers of two is the shift operator, here that would be
2u << (n-1-i)
the suffix u is to ensure that this has the correct type (unsigned). But then you also have to ensure that the value by which you are shifting is not too large, you must guarantee that the corresponding power will still fit into an unsigned. You didn't tell us on what architecture your are, not all have unsigned with 32 bit.
Then your LoadMemory function also looks bogus. As far as I can see there can no guarantee be given that addr (for which you didn't show the type) is smaller than 4096.
Use unsigned int addr = bus32toint(line);

Reading audio rlp

I am tring to get sound samples from microphone through Fez Panda 2. I am using rlp to accomplish that. Here is my code:
int GHAL_AnalogIn_Read(unsigned char channel)
{
return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >>8) & 0x3FF;
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount ,unsigned int *argSize)
{
unsigned char *buffer = (unsigned char*)args[0];
int buffer_lengh = argSize[0];
unsigned char channel = *(unsigned char*)args[1];
int i=0;
while(i<buffer_lengh)
{
buffer[i] = GHAL_AnalogIn_Read(channel);
i++;
RLPext->Delay(100);
}
return 0;
}
The problem is that I need float values not unsigned char because I'm performing fft on these sound samples. So I need modification that will provide me float values. Any ideas?
Have you got experience with C? Especially with the meaning of * and &? * means: get the value pointed by address. So void ** args says someting like 'get the value pointed by the value obtained from address'. void is used to freely input anything you like. As you can not put whole structures or objects in an argument, you provide the pointer (an address) to a structure or object. By using the * you obtain the value on the address of the argument.
In C you do not pass whole arrays in an argument, you pass on the address of the first index.
Now you could simply re-factor your function to be something like:
int ReadAudio(unsigned int *generalArray, float arg, unsigned int argsCount ,unsigned int *argSize)
But as void **args is pointing to a buffer now, I think you should know what operation you want to perform on the data collected. An analog read will always provide you with an integer, most ADC (analog - digital - converter) are 10-bit or so.
If a float is 4 bytes on a 32-bit system, you want to mangle your data (unsigned char *buffer) in a 4-byte boundary.
EDIT: I have overlooked this in the documentatio: Note: Parameter of all function in RLP code file must have format follow this:Note: Parameter of all function in RLP code file must have format follow this:. Just cast the buffer bytes to a float by 4 byte boundary and I think you will do fine.

C Buffer overflow Display message (Using Ubuntu and DDD)

#include <stdio.h>
#include <stdlib.h>
void badf(int n, char c, char* buffer)
{
int i;
for (i=0; i<n; i++)
{
buffer[i]=c;
}
}
void f(int n, char c)
{
char buffer[16];
badf(n,c,buffer);
}
void message ()
{
printf("Hello\n");
}
int main()
{
f(32,0x08048411);
return 0;
}
This is the code I got so far (got given the base of it and got to stick to it, thats why there is a badf and f function)
The goal is that the program prints the Hello message by overflowing to the Instruction pointer. Using Data display debugger in Ubuntu, I believe the address of this display is 0x0804811.
When I run the program through and use x/16x $esp the next address in the stack is just 1s (am guessing only the last two digits are being taken from the address above)
What am wondering is how I would make the next address the full address and not just the last two digits.
Also the 32 is calculated from 16 (buffer defined above) + 8 (base pointer) + 8 (Instruction pointer)
Thanks in advance for any help as I know this specific problem.
Do not pass the address via an 8bit integer (char) but use a type wide enough ... - that is at least 32bits.
Modify as follows:
void badf(int n, unsigned int u, char* buffer)
...
void f(int n, unsigned int u)
...

Fail to read a value from a struture in C after assigning it

I have strange program behavior while trying to read a value from a structure after assigning a value to it. I'm showing the related structure and function below:
/*Data struct for cor_entry */
struct cor_entry {
struct cor_entry * pre_entry;
struct cor_entry * next_entry;
long long unsigned int entry_data;
};
I've commented out most of my function to highlight the problem:
/* update correlation table */
void cor_table_update(long long unsigned int cor_table_data,
struct cor_entry **cor_table_head_ptr,
struct cor_entry **cor_table_tail_ptr,
int *entry_num,
const int MAX_NUM)
{
struct cor_entry *cor_table_entry;
int cor_hit=0;
//test code
//cor_table_head=cor_table_tail=(struct cor_entry*)calloc(1, sizeof(struct cor_entry));
//printf("original cor_entry_num=%d\n",*entry_num);
////////////////////////code for test///////////////////////////////
cor_table_entry=(struct cor_entry*)calloc(1, sizeof(struct cor_entry));
printf("The cor_table_entry=%x\n",cor_table_entry);
cor_table_entry->entry_data=cor_table_data;
if (cor_table_entry->entry_data==cor_table_data)
{
printf("The assignment is correct!\n");
printf("the cor_enrty_data=%x, stored data=%x,\n",
cor_table_data,
cor_table_entry->entry_data);
}
// ... rest of function
}
And I get this output while running the program:
The cor_table_entry=8c09a58
The assignment is correct!
the cor_enrty_data=8ffc8, stored data=0,
The cor_table_entry=8c09a70
The assignment is correct!
the cor_enrty_data=8ffc8, stored data=0,
The cor_table_entry=8c09a88
The assignment is correct!
the cor_enrty_data=8ffc8, stored data=0,
The cor_table_entry=8c09ae8
Could someone shed some light on this problem? I'm using the GCC-3.4.6 compiler.
Try to compile with -Wall. GCC should then tell you that the sizes of the % format specifiers and the printf() arguments don't match. Try %llx instead of %x. That should fix the issue.
Your problem is probably with the printf, %x is not designed for showing long long unsigned. Split the value before printing it and it shall be what you expect.
You could also use %llx format specifier if your compiler support it.

Resources