I'm on Windows 11 in 64 bit machine and for didactic purpose I'm trying to compile in 32 bit a C code (.c) with linked Assebly code (.s), with the following command:
gcc -m32 <file.c> <file.s> -o <name_file>
but the compilation failed reporting the following error:
C:\Users\david\AppData\Local\Temp\ccQPXOVR.o:e2_main.c:(.text+0x1a): undefined reference to f collect2.exe: error: ld returned 1 exit status
The MinGW version that I use is: x86_64-8.1.0-posix-sjlj-rt_v6-rev0
I think the problem is in the ld linker, because compiling the same files but in 64 bits through the following command: gcc -m64 <file.c> <file.s> -o <name_file> does not give me an error (but it is not what I need, I need to compile them in 32 bits).
Below I report the code files that I should compile
<file.c>
#include <stdio.h>
int f(int x);
int score, trials;
void test(int x, int c) {
trials++;
int r = f(x);
printf("Test %d: %d [corretto: %d]\n", trials, r, c);
score += r == c;
}
int main() {
test(3, -2);
test(4, 5);
test(7, 50);
test(17, 460);
printf("Risultato: %d/%d\n", score, trials);
return 0;
}
<file.s>
.globl f
f:
movl 4(%esp), %ecx
movl %ecx, %eax
imull $2, %eax
imull %ecx, %eax
movl $7, %edx
imull %ecx, %edx
subl %edx, %eax
incl %eax
ret
Any ideas on how I can fix it?
I would hugely appreciate any suggestions or guidance on what to do or try next, as I am a little stuck and unsure from here.
I also try to compile an other C code with -m32 flag without linking anything and it seems to have worked.
I try to install i686-8.1.0-release-posix-sjlj-rt_v6-rev0 but it doesn't seem to change anything when I compile with -m32 .
Related
I have two files, one being main.c and the other prog2.s that contains assembly code. The commands I am running are:
gcc -Wall -g -m32 -c main.c
gcc -Wall -g -m32 -c prog2.s
gcc -Wall -g -m32 -o xtest main.o prog2.o
but on that last command, I am getting an error "undefined reference to 'prog2'" twice because in main.c, I try to call prog2 twice. I tried running the main.c file without the terminal but it produced the same error.
I'm not sure code is needed but so you get an idea of what I am trying to do, here are two code samples from each of the files up until the end of the first task which is to return j-i+2.
main.c
int prog2(int i, int j, int *k, int a[5], int *l);
int main() {
int k = 6;
int l = 0, res;
int a[5] = {7, 0, 8, 0, 3};
res = prog2(6,9,&k,a,&l);
if(res != 9-6+2) {
printf("return value should be=%d; got=%d\n", 9-6+2, res);
assert(0);
}
.globl prog2
prog2:
#Setup Code
pushl %ebp
movl %esp, %ebp
pushl %ebx
# j - i + 2
movl 12(%ebp), %eax
movl 8(%ebp), %ecx
subl %ecx, %eax
addl $2, %eax
I want to write a mixed language program where part of the code will be written in C, and part of the code in assembly. I was given a sample code, so i know what should my work look like.
.globl _addArrayinA
_addArrayinA:
pushl %ebp
movl %esp,%ebp
subl $8,%esp
movl 8(%ebp), %ebx
xorl %esi,%esi
xor %eax,%eax
bak:
addl (%ebx),%eax
addl $4,%ebx
incl %esi
cmpl $10, %esi
jne bak
movl %ebp, %esp
popl %ebp
ret
# Return value is in %ea
Above is the assembly part.
int addArrayinC(int *myArray, int num)
{
int c;
int i;
c = 0;
for (i=0; i<num; i++)
{c += *myArray;
myArray++;
}
return (c);
}
This is the second function written in C.
And below is the main file, which is supposed to use two functions above.
#include <stdio.h>
#include <stdlib.h>
extern int addArrayinC(int *numbers,int count);
extern int addArrayinA(int *numbers, int count);
int main(void) {
int mynumbers[10]={1,2,3,4,5,6,7,8,9,0};
int sum;
sum = addArrayinC(mynumbers, 10);
printf("\nThe sum of array computed in C is : %d ",sum);
sum = addArrayinA(mynumbers, 10);
printf("\nThe sum of array computed in assembly is : %d ",sum);
return EXIT_SUCCESS;
}
I tried to open these three files in codeblocks, but could not get to run them. I have no idea how to run a mixed language program. Generally, I use cloud9 for compilations of code. Anyways... How can i run code like this?
No problem here. Please note: the extension of the assembler source file has to be .s or .S(upper case if you want the file to be preprocessed e.g. for #define).
fun.c
unsigned int fun ( unsigned int x )
{
return(x+1);
}
build and examine
gcc -c -O2 fun.c -o fun.o
objdump -D fun.o
producing
0000000000000000 <fun>:
0: 8d 47 01 lea 0x1(%rdi),%eax
3: c3 retq
So we can make fun.s
.globl fun
fun:
lea 0x1(%rdi),%eax
retq
as fun.s -o fun.o
objdump -D fun.o
0000000000000000 <fun>:
0: 8d 47 01 lea 0x1(%rdi),%eax
3: c3 retq
C code so.c
#include <stdio.h>
unsigned int fun ( unsigned int x );
int main ( void )
{
printf("%u\n",fun(1));
printf("%u\n",fun(2));
printf("%u\n",fun(3));
return(0);
}
gcc lets you feed it assembly language
gcc so.c fun.s -o so
./so
2
3
4
as well as objects
gcc so.c fun.o
./so
2
3
4
so you dont have to mess with the linker directly
I am using GCC in 32-bit mode on a Windows 7 machine under cygwin. I have the following function:
unsigned f1(unsigned x, unsigned y)
{
return x*y;
}
I want the code to do an unsigned multiply and as such I would expect it to generate the mul instruction, not the imul instruction. I compile the program
with the following command:
gcc -m32 -S t4.c
The generated assembly code is:
.file "t4.c"
.text
.globl _f1
.def _f1; .scl 2; .type 32; .endef
_f1:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
imull 12(%ebp), %eax
popl %ebp
ret
.ident "GCC: (GNU) 4.8.2"
I believe that the generated code has the wrong multiply instruction in it but I find it hard to believe that GCC has such a simple bug. Please comment.
The compiler relies on the "as-if" rule: No standard conforming program can detect a difference between what this program does and what the program should do, since the lowest 32 bits of the result are the same for both instructions.
I am trying to take a look at a test program my professor gave us, but I am having trouble compiling it. I am on Ubuntu 14.04. I am compiling it with
gcc -Wall test.c AssemblyFunction.S -m32 -o test
I was having problems running the code on a 64-bit machine and read that adding -Wall and -m32 will allow it to work. Doing that fixed the first problem I had, but now I am getting the error: undefined reference to `addnumbersinAssembly'.
Here is the C file
#include <stdio.h>
#include <stdlib.h>
extern int addnumbersinAssembly(int, int);
int main(void)
{
int a, b;
int res;
a = 5;
b = 6;
// Call the assembly function to add the numbers
res = addnumbersinAssembly(a,b);
printf("\nThe sum as computed in assembly is : %d", res);
return(0);
}
And here is the assembly file
.global _addnumbersinAssembly
_addnumbersinAssembly:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp), %eax
addl 12(%ebp), %eax # Add the args
movl %ebp,%esp
popl %ebp
ret
Thank you for your time. I have been trying to figure this out for hours, so I appreciate any help.
I believe that with GCC you are going to want to remove the _ in your assembler file. So these lines:
.global _addnumbersinAssembly
_addnumbersinAssembly:
Should be:
.global addnumbersinAssembly
addnumbersinAssembly:
More information on this issue can be found in this StackOverflow question/answer.
The -m32 compile parameter is needed because the assembly code you have needs to be rewritten to support some 64 bit operations. In your case it was stack operations. The -Wall isn't needed to compile but it does turn on many more warnings.
#include <stdio.h>
int main()
{
char s[200]
int a=123;
int b=&a;
scanf("%50s",s);
printf(s);
if (a==31337)
func();
}
The aim is to execute a format string attack - to execute func() by inputting a string. I tried to use %n to overwrite the variable but I came to conclusion is that it is impossible without displaying b variable first and I have no idea how. Any hint would be appreciated. Sorry for my bad english.
Let's try with and without printing:
$ cat > f.c << \EOF
#include <stdio.h>
void func() {
fprintf(stderr, "func\n");
}
int main()
{
char s[200];
int a=123;
int b=&a;
#ifdef FIXER
fprintf(stderr, "%p\n", b); /* make "b" actually used somewhere */
#endif
scanf("%50s",s);
printf(s);
if (a==31337)
func();
}
EOF
$ gcc --version | head -n 1; uname -m
gcc (Debian 4.7.2-5) 4.7.2
i686
$ gcc -S f.c -o doesnt_work.s
f.c: In function 'main':
f.c:10:11: warning: initialization makes integer from pointer without a cast [enabled by default]
$ gcc -S -DFIXER f.c -o does_work.s
f.c: In function 'main':
f.c:10:11: warning: initialization makes integer from pointer without a cast [enabled by default]
$ gcc doesnt_work.s -o doesnt_work; gcc does_work.s -o does_work
$ echo '%31337p%n' | ./does_work > /dev/null
0xbfe75970
func
$ echo '%31337p%n' | ./doesnt_work > /dev/null
Segmentation fault
As stated in the question, we clearly see that without printing b first it fails.
Let's compare what is hapenning inside:
$ diff -ur does_work.s doesnt_work.s
--- does_work.s 2013-02-06 03:17:06.000000000 +0300
+++ doesnt_work.s 2013-02-06 03:16:52.000000000 +0300
## -29,8 +29,6 ##
.size func, .-func
.section .rodata
.LC1:
- .string "%p\n"
-.LC2:
.string "%50s"
.text
.globl main
## -48,15 +46,9 ##
movl $123, 16(%esp)
leal 16(%esp), %eax
movl %eax, 220(%esp)
- movl stderr, %eax
- movl 220(%esp), %edx /* !!! */
- movl %edx, 8(%esp) /* !!! */
- movl $.LC1, 4(%esp)
- movl %eax, (%esp)
- call fprintf
leal 20(%esp), %eax
movl %eax, 4(%esp)
- movl $.LC2, (%esp)
+ movl $.LC1, (%esp)
call __isoc99_scanf
leal 20(%esp), %eax
movl %eax, (%esp)
On marked lines we see "get value of b into %edx, then put it as 3'rd argument in stack."
As printf and scanf use cdecl call convention, the stack remains more or less the same across invocations, so that third argument remains available for the vulnerable printf for setting.
When we don't print b, it does not get into stack to be easily available for our injected format string.
With enough %p%p%p%p%p%p... we should be able to reach our actual a or b anyway, but the limitation of 50 input characters is getting in our way.