Since my last question was closed because of bad code style and typo, I reviewed it and ask for help again.
I'm trying to resolve a .exe file with PE format. Here is part of my code
#include "PE_resolve.h"
#define SIZEOF_SECTION_HEADER 0x28
/*load filebuffer into Imagebuffer*/
int Read_2_ImageBuffer(void **p_filebuffer, void **p_Imagebuffer,long filesize);
/*helper function*/
inline void * Get_NT_POS(void **p_filebuffer);
inline void * Get_FileHeader_POS(void **p_filebuffer);
inline void * Get_Opt_FileHeader_POS(void **p_filebuffer);
int main(){
return 0;
}
int Read_2_ImageBuffer(void **p_filebuffer, void **p_Imagebuffer,long filesize){
/*allocate memory for imagebuffer*/
void *Opt_PE_Header = Get_Opt_FileHeader_POS(p_filebuffer); //THE ERROR LINE
DWORD SizeOfImage = *(DWORD*) ((BYTE *)Opt_PE_Header + 0x38);
*p_Imagebuffer = malloc(SizeOfImage);
if(*p_Imagebuffer == NULL){
printf("can't allocate enough heap memory\n");
exit(EXIT_FAILURE);
}
memset(*p_Imagebuffer,0,SizeOfImage);
/*.....something deal the memory.....*/
return 0;
}
inline void * Get_NT_POS(void **p_filebuffer){
/*return void * point to NT_header in filebuffer*/
DWORD offset = *(DWORD*)((BYTE *)*p_filebuffer + 0x3c);
return (BYTE *)*p_filebuffer + offset;
}
inline void * Get_FileHeader_POS(void **p_filebuffer){
/*return void * point to PE_header in filebuffer*/
void *nt_pos = Get_NT_POS(p_filebuffer);
return (BYTE *)nt_pos + sizeof(DWORD);
}
inline void * Get_Opt_FileHeader_POS(void **p_filebuffer){
/*return void * point to option_PE_header in filebuffer*/
void *fileheader_pos = Get_FileHeader_POS(p_filebuffer);
return (BYTE *)fileheader_pos + 0x14;
}
And this is PE_resolve.h
#ifndef __PE_resolve_header
#define __PE_resolve_header
#define IMAGE_SIZEOF_SHORT_NAME 8
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char BYTE;
typedef short WORD;
typedef int DWORD;
typedef struct _IMAGE_SECTION_HEADER {
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
union {
DWORD PhysicalAddress;
DWORD VirtualSize;
} Misc;
DWORD VirtualAddress;
DWORD SizeOfRawData;
DWORD PointerToRawData;
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics;
} _IMAGE_SECTION_HEADER;
#endif
when I compile it with MinGW, it follows with undefined reference to `Get_Opt_FileHeader_POS'
C:\MinGW\bin\gcc.exe -g D:\Compile\PE_resolve\PE_loader.c -o D:\Compile\PE_resolve\PE_loader.exe
c:/mingw/bin/../lib/gcc/mingw32/8.2.0/../../../../mingw32/bin/ld.exe: C:\Users\15205\AppData\Local\Temp\ccadB6tt.o: in function `Read_2_ImageBuffer':
D:/Compile/PE_resolve/PE_loader.c:52: undefined reference to `Get_Opt_FileHeader_POS'
As you see, I implement all functions in this .c file with prototype at the beginning.
I'm a little frustrated. Could you please tell me the reason that cause the ERROR ?
Thx :(
You can add the static keyword before every inline function.
By doing that you force the linker to include the function symbol in the symbol table:
static inline void *Get_Opt_FileHeader_POS(void **p_filebuffer);
Another option is to simply remove the inline keyword.
Related
I'm getting this error:
list.c list.h types.h
list.c: In function 'List_push':
list.c:11:23: error: invalid initializer
--- void *values[len] = ls->values);
EDIT:
Now, with my current code (I've done undos/redos that removed somethings), I get this error instead:
Why?
Basically I've a List structure which declares an variable-length array, containing void pointers (what I want is pointers to any data type). You can see it below at the list.h file.
I've tried a mix of changes in list.c (i.e., *values[pos++] = ..., etc...), but doing these changes it only results in worse gcc errors.
wscom.c
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include "types.h"
int main() {
List ls;
// TEST: Put a value pointer at index 0
uint8 value = 0x41;
List_push(&ls, 1, &value);
printf("%c",
*(char*) List_getindex(&ls, 0)
);
return 0;
}
types.h
#ifndef hydroTrackerTypesH
#define hydroTrackerTypesH
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long long uint32;
#endif
list.h (Declarations)
#ifndef hydroTrackerListH
#define hydroTrackerListH
#include "types.h"
typedef struct {
uint32 length;
void *values[];
} List;
void List_push(List *ls, uint8 count, ...);
void *List_getindex(List *ls, uint32 i);
void List_setindex(List *ls, uint32 i, void *v);
#endif
list.c (Defns.)
#include "list.h"
#include "types.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
static size_t PointerSize =
sizeof(void*);
void List_push(List *ls, uint8 count, ...) {
uint32 len = ls->length;
void *values[len] = ls->values;
uint32 sum = len + count;
realloc(&values, sum * PointerSize);
ls->length = sum;
va_list newVals;
va_start(newVals, count);
uint8 pos = len;
while(count--)
values[pos++] = va_arg(newVals, void*);
va_end(newVals);
}
void *List_getindex(List *ls, uint32 i) {
return (void *)(ls->values[i]);
}
//void List_setindex(List *ls, uint32 i, void *v);
This is a little bit long for a comment.
Thus, I make it an answer.
I try to show you how pointers and arrays are related to each other:
#include <stdlib.h>
#include <stdio.h>
int main()
{
/* The compiler allocates space for "Hello" and '\0' (5 + 1 chars)
* and stores the address in aString1.
*/
const char *aString1 = "Hello";
/* The compiler allocates 10 chars and initializes
* it with "World" (and the '\0' for terminator).
*/
const char aString2[10] = "World";
/* The compiler determines length of initializer "I'm here."
* (9 + 1) and allocates the array of appropriate size.
*/
const char aString3[] = "I'm here.";
/* allocate storage for array (3 const char*) */
#if 0 /* the usual way */
const char **array = malloc(3 * sizeof (const char*));
#else /* how Matheus wants to do it */
const char **array = NULL;
array = realloc(array, 3 * sizeof (const char*));
#endif /* 0 */
/* assign contents (using it like an array) */
array[0] = aString1;
array[1] = aString2;
array[2] = aString3;
/* apply array to another variable array2 */
const char **array2 = array; /* assigns the address only */
/* use it: */
printf("array2[0]: '%s', array2[1]: '%s', array2[2]: '%s'\n",
array2[0], array2[1], array2[2]);
/* throw away storage of array (and array2) */
free(array);
/* Attention! array, array2 become wild pointers at this point
* and may not be accessed (except new, valid addresses are assigned).
* However, aString1, aString2, aString3 are still intact.
*/
printf("aString1: '%s', aString2: '%s', aString3: '%s'\n",
aString1, aString2, aString3);
/* done */
return 0;
}
The sample can be tested on ideone.com.
The sample output is:
array2[0]: 'Hello', array2[1]: 'World', array2[2]: 'I'm here.'
aString1: 'Hello', aString2: 'World', aString3: 'I'm here.'
Update:
So, I finally looked again on to the question & answer of Matheus and tried to fix it according to his intention (or how I understood it). I based it on Matheus' implementation and remarked modified codes by comments:
list.h:
#ifndef LIST_H
#define LIST_H
#if 0 /* not necessary to define these types */
#include "types.h"
#else /* they are already available in a (better) portable manner: */
#include <stdint.h>
/* Btw. I had to change:
* uint8 -> uint8_t
* uint32 -> uint32_t
*/
#endif /* 0 */
typedef struct {
uint32_t length;
#if 0 /* gcc ERROR: */
/* list.c:17:3: error: invalid use of flexible array member
* ls->values = NULL;
*/
void *values[];
#else /* (not) 0 */
void **values;
#endif /* 0 */
} List;
void List_init(List *ls);
void List_push(List *ls, uint8_t count, ...);
void* List_getindex(List *ls, uint32_t i);
void List_setindex(List *ls, uint32_t i, void *v);
#endif /* LIST_H */
list.c:
#include "list.h"
#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#if 0 /* no need for a variable (with storage */
static size_t PointerSize = sizeof(void*);
#else /* use enum instead (constant) */
enum { PointerSize = sizeof(void*) };
#endif /* 0 */
void List_init(List *ls)
{
ls->length = 0;
/* This is important: */
ls->values = NULL;
/* or 1st realloc() in List_push() may have Undefined Behavior.) */
}
void List_push(List *ls, uint8_t count, ...)
{
uint32_t len = ls->length;
uint32_t sum = len + count;
void **values = realloc(ls->values, sum * PointerSize);
if (!values) {
/* realloc() failed! Bail out before destroying the existing data. */
return;
}
ls->length = sum;
ls->values = values;
/* assign new contents */
va_list newVals;
va_start(newVals, count);
#if 1 /* the readable way: */
int pos = len;
while (count--) values[pos++] = va_arg(newVals, void*);
#else /* the hackish C style way: */
values += len;
while (count--) *values++ = va_arg(newVals, void*);
#endif /* 1 */
va_end(newVals);
}
void* List_getindex(List *ls, uint32_t i)
{
return ls->values[i];
}
wscom.c:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "list.h"
int main()
{
List ls;
/* Put a value pointers at indices 0, 1, 2 */
uint8_t value1 = 0x41, value2 = 0x42;
uint8_t value3[3] = { 0x43, 0x44, 0x45 };
List_init(&ls);
List_push(&ls, 3, &value1, &value2, value3);
/* Check whether list contents can be retrieved again */
if ((*(uint8_t*)List_getindex(&ls, 0)) == 0x41) {
printf("List entry 0 is correct.\n");
}
if ((*(uint8_t*)List_getindex(&ls, 1)) == 0x42) {
printf("List entry 1 is correct.\n");
}
{ uint8_t *values = List_getindex(&ls, 2);
if (values[0] == 0x43
&& values[1] == 0x44
&& values[2] == 0x45) {
printf("List entry 2 is correct.\n");
}
}
/* Done. */
return 0;
}
In one of my comments, I stated that void *values[]; in struct List might be OK. Ahem, I was wrong. gcc remarks this as error when I tried to use it in list.c. So, actually, it is OK but not for what I intend it to use.
Finally, my sample session (using gcc in cygwin on Windows 10):
$ gcc -std=c11 -o wscom wscom.c list.c
$ ./wscom
List entry 0 is correct.
List entry 1 is correct.
List entry 2 is correct.
$
2nd Update:
(I believe) I realized the missing piece of Matheus (considering his Javascript background):
There are no dynamic arrays in C (in opposition to Javascript).
Instead, there are arrays with variable size which may be used only in specific situations:
In C:
Definition of arrays with variable size in global variables is prohibited. (The compiler needs to know how many bytes to allocate for storage.) This does not exclude something like e.g.
int array[] = { 1, 2, 3 };
because the compiler determines the size from the initializer (on the right hand side of =).
Declaration of global arrays without explicit size is possible. (The definition with proper size might/must be done somewhere else. The linker will fail if no proper storage definition can be found.)
A local variable (inside a function, storage class auto but not static or extern) might be declared as array with size determined at runtime (from a variable). This feature was introduced in C99 but not (yet) in C++ (at least not until C++11 incl.)
A function parameter might be declared as array with unknown (or any) size. (This is equal to declaring it as a pointer.)
I found a nice answer about this in SO: Dynamic array allocation on stack in C (which I used to prove my own statements above).
The only supported way to have "dynamic arrays" in C is the usage of the standard library functions malloc()/realloc()/free(). However this is better called "dynamic memory" allocation because this applies to any C type (not only arrays).
Disclaimer:
I apologize if I wrote something rubbish about Javascript. I'm the total newbie in Javascript with very less practical experience...
I have 4 files (2 headers, 2 source):
lcd.h,
lcd.c,
azt.h and
azt.c
I included lcd inside azt.
In lcd there's a function WriteMsg which is called inside azt,
it works fine.
But when I add a call to this function in lcd.c, I get the following error
Description Resource Path Location Type
unresolved symbol WriteMsg, first referenced in ./Includes/AutoZeroTracking.obj Joe1000 C/C++ Problem
I understand that I referenced it first at azt files, but this function is referenced in other places and I don't have this problem.
Here's the lcd.h:
#ifndef MSP
#define MSP
#include <msp430g2553.h>
#endif
#include "Utilities.h"
#include "Declarations.h"
#ifndef INCLUDES_LCD_H_
#define INCLUDES_LCD_H_
#define LCD_CALL 1
void InitLCD(unsigned char SDA,unsigned char SCL,unsigned char slaveAddress);
void StartLCD();
inline int ReadyToSend();
void SendToLcd(unsigned char* data, int size);
void WriteToLCD(int clearScreen);
void switchFrom8To4Bits();
void write2x4Bits(unsigned char bits, int is_data);
void writeCommand(unsigned char command);
inline void writeData(unsigned char data);
void ClearScreen();
void WriteWeight();
void WriteWeightMode();
inline void WriteMsg(const char* msg, int msgLen,char msgLocation,int maxDigits);
inline void WriteNum(long num,char location,int maxDigits);
void WriteTare(char num);
#endif /* INCLUDES_LCD_H_ */
here's the azt.h:
#ifndef INCLUDES_AUTOZEROTRACKING_H_
#define INCLUDES_AUTOZEROTRACKING_H_
#include "Declarations.h"
#include "LCD.h"
#include "Utilities.h"
void AZTSetup();
void AZTProcess();
void DisplayAZT();
void GetPreviousAZT();
void GetNextAZT();
void KeyPressedAZTMode(char keyPressed);
inline char HasAZTStopped();
#endif /* INCLUDES_AUTOZEROTRACKING_H_ */
the code in azt.c
void DisplayAZT()
{
WriteMsg(AZT[m_curr_azt],AZTLen[m_curr_azt],0x8A,5);
}
the call in lcd.c
void WriteWeight()
{
WriteNum(CountBy[cnt_by_idx],0x80,2);
WriteNum(NOD[n_o_d_idx],0x83,5);
WriteNum(max_weight,0x89,6);
WriteNum(idx_decimal_point,0x90,1);
WriteMsg(AZT[az_tracking_idx],AZTLen[az_tracking_idx],0x9A,3);
WriteNum(BaudRate[baud_rate_idx],0xC0,6);
WriteNum(PP2Z[percent_p2z_idx],0x9E,2);
WriteNum(wt_zero,0x94,10);
WriteNum(wt_slope,0xD4,10);
/*int i = 0;
for(i = 0; i < WEIGHT_ARR_LEN ; i++)
{
if(display_weight[i] != IGNORE_CHAR)
writeData(display_weight[i]);
}*/
}
Thanks in advance.
I removed the inline and it compiles.
the implementation level of the array-based
#include "stack.h"
void creat_stack(Stack *s) {
s->Top = 0;
}
int isFull(Stack s) {
return (s.Top == Max ? 1 : 0);
}
int isEmpty(Stack s) {
return (s.Top == Max ? 1 : 0);
}
void push(stack_entry e, Stack *s) {
if (!isFull(*s))
s->entry[s->Top++] = e;
else
printf("Error : Stack Overflow\n");
}
void pop(stack_entry *e,Stack *s) {
if(!isEmpty(*s))
*e = s->entry[s->Top--];
else
printf("Error : Stack Underflow\n");
}
the header file stack.h that consists of the prototypes of the functions along with the definition of the stack element type stack_entry.
#pragma once
#include <stdio.h>
#define Max 10
typedef char stack_entry;
typedef struct Stack{
int Top;
stack_entry entry[Max];
}Stack;
void creat_stack(Stack *s);
int isFull(Stack s);
int isEmpty(Stack s);
void push(stack_entry e,Stack *s);
void pop(stack_entry *e, Stack *s);
so my question why i have to include the header file "stack.h" in the "stack.c" file ??
You should have to add the stack.h because this file is it who has all declarations of your typedef define struct and methods
So without then, will be impossible to access any of those informations.
It is the same if you declare a method below the main function and do not declare his signature upstairs the main, you cannot access..
So, all this happens with all include files that you use at the top of your file..
Do not forget C is a sequential language, so you will never know what do you have in the next line if you don't tell the compiler.
check more here
First, don't include "stdio.h" in the header file, you aren't use it there anyway. include it in the source file where you are using it.
You need to include the header file for the "struct stack" and the "define".
If i have this stack abstract type that i've to use :
stack.h:
#ifndef STACK_H
#define STACK_H
typedef enum { STACK_OK, STACK_EMPTY, STACK_FULL } StackStatut;
void pushToStack(void * x);
void * popFromStack(void);
unsigned countStack(void);
#endif
stack.c:
#include "stack.h"
#define MAX_ELEMS 200
static unsigned numbElems = 0;
static void * elems[MAX_ELEMS];
void pushToStack(void * x) {
elems[numbElems++] = x;
}
void * popFromStack(void) {
return elems[--numbElems];
}
unsigned countStack(void){
return numbElems;
}
When i come in my main.c, i know that i've to include stack.h in order to be able to declare a pointer to build a stack.
The point is that i've NO clue how to proceed. I know how to deal with ADT when it's come to a struct but now i'm completly lost.
if i 've let say :
main.c:
#include "stack.h"
int main() {
int i = 1;
int j = 2;
int k ; 3;
// At this point, i know that i need a void * prt
int * prt;
// This is the part where i dont know how to start my stack.
// if i do :
pushToStack(&i);
// i dont know how the number of elem in the stack will be incremented
// I dont know neither how to apply a statut to the stack.
}
Thank you very much !
The stack is intialized in the stack.c
static unsigned numbElems = 0;
static void * elems[MAX_ELEMS];
These two lines create your stack and set the current count to 0
I have the following code in a header file:
#ifndef BUFFER_H
#define BUFFER_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct c_buff
{
void *buffer; // data buffer
void *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
void *head; // pointer to head
void *tail; // pointer to tail
};
void cb_init(c_buff *cb, size_t capacity, size_t sz)
{
cb->buffer = malloc(capacity * sz);
if(cb->buffer == NULL) {
// handle error
}
cb->buffer_end = (char *)cb->buffer + capacity * sz;
cb->capacity = capacity;
cb->count = 0;
cb->sz = sz;
cb->head = cb->buffer;
cb->tail = cb->buffer;
}
#endif
And the following c file
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <common.h>
#include <usart.h>
#include <buffer.h>
struct c_buff usart_buffer;
struct c_buff *usart_buffer_ptr;
cb_init(usart_buffer_ptr, USART_BUFFER_SIZE, sizeof(char));
void initUSART(void) {
SETBIT(UCSR0A, UDRE0);
//SETBIT(UCSR0A, U2X0);
SETBIT(UCSR0C, UCSZ01);
SETBIT(UCSR0C, UCSZ00);
UBRR0 = 25;
SETBIT(UCSR0B, RXCIE0);
SETBIT(UCSR0B, TXCIE0);
SETBIT(UCSR0B, RXEN0);
SETBIT(UCSR0B, TXEN0);
}
ISR(USART_RX_vect) {
char data;
data = UDR0;
UDR0 = data;
}
ISR(USART_TX_vect) {
}
When I try to compile this I get an error that points to this line:
cb_init(usart_buffer_ptr, USART_BUFFER_SIZE, sizeof(char));
And it just says "error: expected ')' before numeric constant".
Google tells me it's some kind of preprocessor error. But I don't see how that could be the case.
I'm new to C so I apologize if it is something totally obvious.
You can't have a naked function call at the top level.
cb_init(usart_buffer_ptr, USART_BUFFER_SIZE, sizeof(char));
is a naked function call. Move that inside main().
You can't run function in global scope. It has to be done in main:
int main(int argc, char *argv[] {
cb_init(usart_buffer_ptr, USART_BUFFER_SIZE, sizeof(char));
}
The problem is that you're attempting to execute a method at the file level.
cb_init(usart_buffer_ptr, USART_BUFFER_SIZE, sizeof(char));
The C language only allows declarations / definitions at this level not actual executed statements. This call needs to be moved into a function definition.