0

Can you let me know what I'm doing wrong?
I'm new to assembly programming and am unfamiliar with the various options in ld.

I've been trying to use the yasm compiler initially but then realised that as is the way to go for the ARM architecture while composing GNU compliant assembly code.

Better luck running as from the binutils package, i.e. the GNU assembler. But the assembly code has to be ARM-compliant.

The following is the code within arm.s:

.text                             /* Start of the program code section */ 
    .global main                      /* declares the main identifier */ 
    .type main, %function
main:    /* Address of the main function */ 
     /* Program code would go here */ 
     BR LR 
     /* Return to the caller */
    .end                              /* End of the program */

The above was throwing an Illegal Instruction error. That can be fixed by substituting ret for BR LR. This is new to ARM V8.


ARM, a RISC architecture, is not supported by YASM.

My build file is as follows:

#/usr/bin/env bash 
#display usage
[ $# -eq 0 ] && { echo "Usage: $0 <File Name without extension> ";exit 1; }
set +e
rm -f $1.exe $1 $1.o
as -o $1.o $1.s
[ -e $1.o ] && { file $1.o;}
gcc -s -o $1.exe $1.o -fpic
ld -s -o $1  -pie --dynamic-linker /system/bin/linker64 /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o  $1.o -lc -lgcc -ldl /data/data/com.termux/files/usr/lib/crtend_android.o
[ -e $1.exe ] && { file $1.exe;nohup ./$1.exe; }  
[ -e $1 ] && { file $1;nohup ./$1;}
set -e

The code was causing either a segmentation fault or a bus error earlier.

I was able to run a program or two without any segmentation or bus errors with the updated build file above. I set up the build file to produce two executables, one using gcc and the other ld, since some online tutorials use ld instead of gcc for the linking step. Using the verbose setting of gcc, you can look at the options passed to the linker and thus mimic the same for the linker independently.

There may be some redundant settings that I've missed.

You can access updates to the source code and build file at Learn Assembly.

Check out this resource from Keil here. arm Keil product guides

More resources:

https://thinkingeek.com/2016/10/08/exploring-aarch64-assembler-chapter1/

How to link a gas assembly program that uses the C standard library with ld without using gcc?

While the above problem appears to be fixed for now, I have errors running the following code:

.text
.global main
main:
mov w0, #2
mov w7, #1 // request to exit program
svc 0

I obtain an illegal instruction error when I try to execute the code.

Secondly, if I alter the main to _start (since I don't want to be using main all the time), I have the following error from the buildrun script.

./buildrun myprogram

  /data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: myprogram.o: in function `_start':    (.text+0x0): multiple definition of `_start'; /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o:crtbegin.c:(.text+0x0): first defined here       /data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o: in function `_start_main':      crtbegin.c:(.text+0x38): undefined reference to `main 
/data/data/com.termux/files/usr/bin/aarch64-linux-android-ld: crtbegin.c:(.text+0x3c): undefined reference to `main'                                  clang-8: error: linker command failed with exit co
de 1 (use -v to see invocation)
ld: myprogram.o: in function `_start':            (.text+0x0): multiple definition of `_start'; /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o:crtbegin.c:(.text+0x0): first defined here       ld: /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o: in function `_start_main':              crtbegin.c:(.text+0x38): undefined reference to `main'
ld: crtbegin.c:(.text+0x3c): undefined reference to `main'

How do I create programs with entry points other than main?

I want to be able to :

  1. Create a statically linked executable that works.

  2. Create an executable that has a function named _start instead of main.

This file builds static executables that don't use main or call any library calls.

  1. Create a dynamically linked executable with an entry point other than main. My build file handles this, sort of, with the entry point as second parameter.

  2. Create an executable that uses supervisor call svc to exit without throwing an illegal instruction error as against using ret.

I was able to call svc by setting the system call number in register X8 as against W7 in version 7 ARM. Additionally, ARM 64 has renumbered the system call numbers as per the following header file. https://github.com/torvalds/linux/blob/v4.17/include/uapi/asm-generic/unistd.h https://reverseengineering.stackexchange.com/q/16917

.data .balign 8 labs: .asciz "Azeria Labs\n" //.asciz adds a null-byte to the end of the string .balign 8 after_labs: .set size_of_labs, after_labs - labs .balign 8 addr_of_labs: .dword labs .balign 8 .text .global main

main:
mov x0, #1 //STDOUT ldr x1,addr_of_labs //memory address of labs mov w2, #size_of_labs //size of labs mov x8,#64 svc #0x0 // invoke syscall _exit: mov x8, #93 //exit syscall svc #0x0 //invoke syscall

The above code was ported from the example code listed below. https://azeria-labs.com/writing-arm-shellcode/ Compacting the data section into one instead of splitting it as in the example from the site mitigates the relocation errors while linking.

Other useful references:

https://thinkingeek.com/2013/01/09/arm-assembler-raspberry-pi-chapter-1/

*Check the comment by ehrt74 on the above post for the motivation to explore svc call further. *

Linus Fernandes
  • 498
  • 5
  • 30

1 Answers1

0

Yasm is an x86 assembler. It cannot produce executables for an ARM processor.

The tutorials you are working with are describing x86 assembly. They are intended to be followed on an x86 system.

  • I'm aware of that now. When I started out, I wasn't. – Linus Fernandes Apr 05 '19 at 06:02
  • Yes, I can't find any quick start resources for the ARM V8 assembly language. You can check out my source from Git if you like to see what's the problem with my programs. I'm a newbie to assembly coding on any architecture. I feel I should first pick up assembly on one platform before venturing into fixing what's wrong on Termux. I'll need to get myself familiar with assembly programming first. Secondly, the resources listed for ARM will need to be cross referenced with any other programming resources in x86 format and then altered to run them on ARM. That's not a trivial exercise. – Linus Fernandes Apr 06 '19 at 13:36
  • Arm has two variants of assembly language. UAL and GNU Assembly. Using as requires the latter. – Linus Fernandes Apr 06 '19 at 13:37