Skip to content

Commit c88f115

Browse files
committed
Updated the explaination of ADRP in the README
1 parent 61fc9ca commit c88f115

File tree

1 file changed

+16
-22
lines changed

1 file changed

+16
-22
lines changed

README.md

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,30 @@ Until then, I have removed the _AsMain_ target.
4949

5050
## Listing 4-8
5151

52-
Besides the changes that are common, we face a new issue, which is described in the book in Chapter 5: Darwin does not like `LSR X1, =symbol`, and in the case of `ASR X1, symbol` our data has to be in the read-only `.text` section. In this sample however, we want writable data.
52+
Besides the changes that are common, we face a new issue, which is described in the book in Chapter 5: Darwin does not like `LSR X1, =symbol`, we will get the error `ld: Absolute addressing not allowed in arm64 code`. If we use `ASR X1, symbol`, our data has to be in the read-only `.text` section. In this sample however, we want writable data.
5353

5454
On Darwin "All large or possibly nonlocal data is accessed indirectly through a global offset table (GOT) entry. The GOT entry is accessed directly using RIP-relative addressing." [Apple Documentation](https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/MachOTopics/1-Articles/x86_64_code.html#//apple_ref/doc/uid/TP40005044-SW1)
5555

5656
And by default, on Darwin all data contained in the `.data` section, where data is writeable, is "possibly nonlocal".
5757

58-
Thankfully, @claui pointed me to the working solution:
58+
Thankfully, @claui gave me a pointer into the right direction, and the full answer can be found [here](https://reverseengineering.stackexchange.com/a/15324):
59+
> The `ADRP` instruction loads the address of the 4KB page anywhere in the +/-4GB (33 bits) range of the current instruction (which takes 21 high bits of the offset). This is denoted by the `@PAGE` operator. then, we can either use `LDR` or `STR` to read or write any address inside that page or `ADD` to to calculate the final address using the remaining 12 bits of the offset (denoted by `@PAGEOFF`).
5960
61+
So this:
6062
```
61-
ADRP X1, hexstr@PAGE
62-
ADD X1, X1, hexstr@PAGEOFF
63+
LDR X1, =outstr // address of output string
64+
```
65+
66+
becomes this:
67+
```
68+
ADRP X1, outstr@PAGE // address of output string
69+
ADD X1, X1, outstr@PAGEOFF
6370
```
64-
[ARM Documentation](https://developer.arm.com/documentation/dui0802/b/A64-General-Instructions/ADRP)
6571

6672
## Chapter 5
6773

74+
The important differences in memory addressing for Darwin were already addresed above.
75+
6876
### Listing 5-1
6977
The `quad`, `octa` and `fill` keywords apparently must be in lowercase for the llvm assembler. (See bottom of this file)
7078

@@ -74,22 +82,7 @@ Changes like in Chapter 4
7482

7583
## Listing 6-3 to 6-5
7684

77-
Learned something new: `@GOTPAGE` operand worked for us, but only by chance: It gave us the base address of the Global Offest Table. When we debug the `upper` sample from Chapter 5, we see that actually the `instr` is converted in place, and the `outstr` is not touched.
78-
79-
The correct answer can be found [here](https://reverseengineering.stackexchange.com/a/15324): _"The `ADRP` instruction loads the address of the 4KB page anywhere in the +/-4GB (33 bits) range of the current instruction (which takes 21 high bits of the offset). This is denoted by the `@PAGE` operator. then, we can either use `LDR` or `STR` to read or write any address inside that page or `ADD` to to calculate the final address using the remaining 12 bits of the offset (denoted by `@PAGEOFF`)."_
80-
81-
So this:
82-
```
83-
LDR X1, =outstr // address of output string
84-
```
85-
86-
becomes this:
87-
```
88-
ADRP X1, outstr@PAGE // address of output string
89-
ADD X1, X1, outstr@PAGEOFF
90-
```
91-
92-
Unrelated, the Darwin `write` system call apparently requires the length of the output to be stored in `X2`, whereas this is either a bug in the original code (unlikely), or Linux can work with zero-termination:
85+
The Darwin `write` system call apparently requires the length of the output to be stored in `X2`, whereas this is either a bug in the original code (unlikely), or Linux can work with zero-termination:
9386
```
9487
MOV X2, X0 // First, save the length into X2
9588
```
@@ -106,8 +99,9 @@ No changes in the core code were required, but I created a SwiftUI app that will
10699
## Additional references
107100

108101
* [What is required for a Mach-O executable to load?](https://stackoverflow.com/a/42399119/1600891)
109-
* Mac OS X Internals, A Systems Approach. Amit Singh, 2007
102+
* [Mac OS X Internals, A Systems Approach](https://www.pearson.ch/Informatik/Macintosh/EAN/9780134426549/Mac-OS-X-Internals) Amit Singh, 2007
110103
* [Darwin Source Code](https://opensource.apple.com/source/xnu/)
104+
* [ARM Archicture Reference Manual](https://static.docs.arm.com/ddi0487/ca/DDI0487C_a_armv8_arm.pdf)
111105

112106
## One More Thing…
113107
"The C language is case-sensitive. Compilers are case-sensitive. The Unix command line, ufs, and nfs file systems are case-sensitive. I'm case-sensitive too, especially about product names. The IDE is called Xcode. Big X, little c. Not XCode or xCode or X-Code. Remember that now."

0 commit comments

Comments
 (0)