How do I use the ARM assembler in XCode? - ios

Just for educational purposes, I would like to add a function to an existing iPhone app, written in ARM assembly. I don't need a tutorial on ARM assembly in general, because I already read too many of them. I just don't know how to actually run the code!
What I would like to do is something like:
useless.h:
void useless();
useless.s:
useless:
bx lr
If this also works on the simulator it would be fine... On the simulator, the .s file would not compile, so I should maybe do something like:
useless.s:
#if I_AM_ARM
useless:
bx lr
#endif
useless.c:
#if !I_AM_ARM
void useless()
{
}
#endif
I know the syntax I use is broken, but how do I write it correctly? (Breaking an app on the simulator just because I want to try some inline assembly is no option...)
The second-best option would be to use inline assembly, but I would strongly prefer non-inline assembly.
Thanks!
Edit: I want to learn ARM assembly, so I would like to find a method to compile ARM assembly code, and to EXECUTE ARM assembly code.

I finally found the answer myself. It's actually not that hard. I only solved it for the 32-bit ARM version though.
useless.h:
void useless();
useless.s:
#ifdef __arm__
.syntax unified
.globl _useless
.align 2
.code 16
.thumb_func _useless
_useless:
//.cfi_startproc
bx lr
//.cfi_endproc
// CFI means Call Frame Information
// Optionally. Use for better debug-ability.
#endif
useless.c:
#ifndef __arm__
void useless()
{
}
#endif
Notes:
The CLANG ARM Assembler syntax is a bit different from what you see in example all over the web. Comments start with // and /* multiline comments */ are also supported. It also understands the standard C preprocessor. The function has to be defined as a Thumb function, if you specify an arm function (.code 32) the program will just crash. The line .thumb_func _useless can be ommited and it works still. I have no Idea what it means. If you omit the .code 16 line, the program crashes.
about the #ifdef. For ARMv7, __arm__ is defined. For ARMv8, i.e. the 64bit-variant on the iPhone 5S, __arm__ is not defined, but __arm64__ is defined instead. The above code does not work for the 64bit-ARM-version. Instead, the implementation from useless.c will be used. (I didn't forget ARMv7s, I just don't have a device with that arch in my hands currently, so I cannot test.)

The simulator doesn't use arm. you'll have to write x86_64 assembly if you want it to run on the simulator. (probably).

The best way to learn is to take a look at actual working examples, see my blog post about ARM iOS timing. This example Xcode project shows how to mix ARM ASM and C impls of a function. There is also a very accurate timing module to run your code N times, because accurate timing is the hard part when it comes to optimizing the code.

You can emulate ARM-Ubuntu with QEmu (there are some Windows ports of it, e.g. http://lassauge.free.fr/qemu/ ). If you are on Windows, you may need to emulate x86_64-Ubuntu in the middle. To create an ARM image you can follow the steps from this question: Black screen in QEmu for ARM-Ubuntu (how to get GUI?) (yes, unfortunately, you get no GUI with these steps, just a console to the ARM-Ubuntu machine, and you have to do the steps from Ubuntu). Then you can cross-compile your C++/C/Assembly programs from Windows/Ubuntu host to ARM-Ubuntu target.
clang++.exe -Wall test1.cpp -o test1exe -std=c++14 -Ipath-to-arm-linaro/arm-linux-gnueabihf/include/c++/5.3.1 -Ipath-to-arm-linaro/arm-linux-gnueabihf/include/c++/5.3.1/arm-linux-gnueabihf -ffunction-sections -fdata-sections --sysroot=path-to-arm-linaro/arm-linux-gnueabihf/libc --target=arm-unknown-linux-gnueabihf -Bpath-to-arm-linaro/arm-linux-gnueabihf/bin/
For cross-compilation you would need to download and roll out a toolchain, e.g. gcc-linaro-5.3-2016.02-i686-mingw32_arm-linux-gnueabihf.tar.xz (Windows/MinGW) from https://releases.linaro.org/components/toolchain/binaries/latest-5/arm-linux-gnueabihf/ and replace "path-to-arm-linaro" in the above command with the path to the toolchain.

I just started working with iOS. The first thing I tried to do was add asm code to my project and ran into the same problem. The static data is handled slightly differently in 64-bit mode. I discovered how to do it by looking at the assembler output of the compiler. The same .S file will be compiled as both 32 and 64-bit in Xcode, so prepare it like this:
.globl _myfunction
.align 2
my_constant_data:
.byte 0,1,2,3,4,5,6,7
#ifdef __arm__
.thumb_func _myfunction
.syntax unified
.code 16
//
// call from C as my myfunction()
//
_myfunction:
ldr r0,=my_constant_data
< write your thumb-2 code here >
bx lr
#else // or you can use #ifdef __arm64__
//
// Call from C as myfunction()
//
_myfunction:
adrp x0, my_constant_data#PAGE
add x0,x0, my_constant_data#PAGEOFF
< write your Armv8 code here >
ret
#endif

Related

Getting the address of a section with Clang on OSX/iOS

For quite a while I've been using linker sections for registering elements that are used at runtime. I find that it's a simple way to make generic and extensible interface. A particularly useful use-case is something like unit tests or a multitool (e.g. busybox) so one can do something like:
$ ./tool <handler>
Where handler is a simple string that is "looked up" at runtime by walking the linker section. In this way, your parser doesn't have to "know" what commands are supported. It just finds their handlers in the linker section dedicated for them or it doesn't.
With GCC I've been doing something like (you can do this with Clang as well):
#define __tool __attribute__((__section__("tools")))
Then each handler I want to register gets a simple structure (with more or less information as needed)
struct tool {
const char *name;
const char *help;
int (*handler)(int argc, char **argv);
}
Then, for each tool you just do something like (often conveniently wrapped in a macro):
int example_tool0(int argc, char **argv)
{
return -1;
}
static const struct tool example_tool0 = {
.name = "exmaple_tool0",
.help = "usage: ...",
.handler = example_tool0
};
__tool static const struct tool *ptr = &example_tool0;
And used a such:
$ ./tool example_tool0
And because of __tool, each pointer registered in this way is packed into a linker section that can be walked.
Now, on GCC the linker creates two magic variables for each section: __start_SECTION and __stop_SECTION. So, to "walk" all of our registered handlers you just take the size of this section, divide by the size of a pointer, and then strncmp against the name (in this example) in the struct.
All of the above just to say, how can this be done using the OSX/iOS Clang-based toolchain? I would rather not use a custom linker script to achieve this seemingly simple operation.
Is there a way do this on OSX? I have worked around the issue by registering an empty entry at the beginning of the section and at the end. But doing so requires forcing the link order of the object files.
While OSX/iOS uses Clang as their platform compiler, they do not use the LLVM linker. Rather, they implement their own ld64 (which is open source) for whatever reason. So, it may just not be supported. I didn't readily see anything in man ld on OSX, but it's a bit info-dense.
For reference with ELF and GCC
And so this has been answered by others already. I did search, but I must have missed this answer. I've actually looked for an answer to this question many times before but must've never used the right words.
https://stackoverflow.com/a/22366882/2446071
In summary, apparently the linker supports syntax to define these desired symbols yourself:
extern char __start_SECTION __asm("section$start$SEGMENT$SECTION");
extern char __stop_SECTION __asm("section$end$SEGMENT$SECTION");

Calling a function inside iOS static library from command line

We have some functions made available to us in iOS static library. There is a header (.h) and the compiled (.a) file. Is there any way that the functions in the static library can be called from a command line ( either OS X, Windows or Linux )? I have researched this for couple of days now and I am starting to doubt if this is even possible? We don't deal with Apple/iOS/xcode environment and the vendor only has this static library. Any hints? If it is possible in anyway I am open to reading any and very documentation but at this time I am in doubt if this is even possible? thanks
While checking out what is possible, I ran this
lipo -info libExaNumberCalc.a
I ran the above and it says
Architectures in the fat file: libExaNumberCalc.a are : i386 armv7 x86_64 arm64
Wonder if the above adds any hope?
The first thing that springs to mind is that you could write thin wrapper around your library function and build/run it. Something like
// main.c
#include "your_library_header.h"
int main(int argc, char *argv[])
{
// parse & pass parameters if necessary from command line
your_lib_function();
return 0;
}
Build with something like
clang main.c -o output.file -lyourlibrary

How to break inside the constructor of a dylib with gdb on iOS, along with ASLR?

Scene:
I was trying to reverse engineer a mobile substrate dylib. Via IDA, the dylib called MSHookFunction() inside the constructor, and the arguments were from dlopen and dlsym. IDA failed to show the symbols of dlopen and dlsym, so I had to turn to gdb, which could possibly print the 2nd arg of dlsym, a char*, at run time.
Goal:
Break at the very beginning of the constructor of this dylib with gdb.
First Thought:
The constructor of a dylib is executed right after it's loaded, doing all the necessary initializations (Correct me if I'm wrong). So I wrote a command line tool which simply dlopen the dylib and then dlclose it, to run the constructor. FYI, here's the code of the dylib and the command line tool:
// iOSTestDylib.dylib: I'm using [Logos][1] here
%ctor
{
%init;
NSLog(#"snakeninny: ctor of dylib");
}
// iOSTestTool
#include <mach-o/dyld.h>
#include </usr/include/dlfcn.h>
int main(int argc, char **argv, char **envp)
{
NSLog(#"snakeninny: line 6 of command line tool");
void *handle = dlopen("pathOfTheAboveDylib", RTLD_LAZY);
NSLog(#"snakeninny: line 8 of command line tool");
dlclose(handle);
return 0;
}
As you can guess, once I run iOSTestTool, it printed:
snakeninny: line 6 of command line tool
snakeninny: ctor of dylib
snakeninny: line 8 of command line tool
Then setting a break point inside iOSTestDylib.dylib seemed to solve the problem. But I suddenly realized that, before dlopen iOSTestDylib.dylib, the ASLR offset of iOSTestDylib.dylib was unknown, therefore the address of the bp was uncertain. Meanwhile, after dlopen, though we could figure out the ASLR offset, the ctor was already executed, so bp became meaningless. In either situation, I couldn't break inside the constructor of a dylib. Mission failed, and neither did I have a second thought, nor a plan B :(
Question:
What should I do to reach my goal?

Code coverage with Xcode 4.2 - Missing files

I followed Claus's post to set up code coverage on Xcode 4.2 with LLVM 3.0. I'm able to see test coverage files, but they're only for my unit test classes, not my actual project classes. I've tried setting Generate Test Coverage Files and Instrument Program Flow to Yes on my main target, but that didn't help, as it failed with the following error:
fopen$UNIX2003 called from function llvm_gcda_start_file
To clarify, I don't think that's even the right approach - I just tried it to see if it would generate code coverage on my project classes.
At this point, I'd be happy to try anything that gets code coverage working on my app. Any suggestions?
You are expecting linker problem, profile_rt library uses fopen$UNIX2003 and fwrite$UNIX2003 functions instead of fopen and fwrite.
All you need is to add the following .c file to your project:
#include <stdio.h>
FILE *fopen$UNIX2003( const char *filename, const char *mode )
{
return fopen(filename, mode);
}
size_t fwrite$UNIX2003( const void *a, size_t b, size_t c, FILE *d )
{
return fwrite(a, b, c, d);
}
This code just remaps the missing functions to standard ones.
Note on $UNIX2003 suffix:
I've found an Apple document saying:
The UNIX™ conformance variants use the $UNIX2003 suffix.
Important: The work for UNIX™ conformance started in Mac OS 10.4, but was not completed until 10.5. Thus, in the 10.4 versions of libSystem.dylib, many of the conforming variant symbols (with the $UNIX2003 suffix) exist. The list is not complete, and the conforming behavior of the variant symbols may not be complete, so they should be avoided.
Because the 64-bit environment has no legacy to maintain, it was created to be UNIX™ conforming from the start, without the use of the $UNIX2003 suffix. So, for example, _fputs$UNIX2003 in 32-bit and _fputs in 64-bit will have the same conforming behavior.
So I expect libprofile_rt to be linked against 10.4 SDK.
I use CoverStory http://code.google.com/p/coverstory/ a GUI for .gcda and .gcno files.
The documentation explains the settings needed to generate these files http://code.google.com/p/coverstory/wiki/UsingCoverstory.

How to link to NTQueryKey in Kernel Mode

For the life of me I can't figure out how to resolve the declared NTQueryKey value in my device driver. I looked for a device driver forum, but didn't find one.
Can someone point me to the right place? OSR isn't very responsive with dumb questions like how to link to NTQueryKey.
Here is my prototype:
NTSYSAPI NTSTATUS NTAPI NtQueryKey(HANDLE, KEY_INFORMATION_CLASS, PVOID, ULONG, ULONG *);
and it compiles fine, but the linker doesn't like it.
Thanks
NtXXXX functions should not be called from kernel mode. Use the ZwXXXX functions instead. In your case, you want ZwQueryKey. It has the same signature as NtQueryKey, but it performs actions on the x86 required for talking with kernel mode, and it's provided by ntoskrnl.exe rather than by ntdll.dll.
In kernel mode you link to the Zw.... equivalent functions. See Here. NT.... functions are called from user mode (for example the Win32 subsystem would call the NT... functions).

Resources