Запись в выделенную память с помощью sbrk приводит к segfault [duplicate]

Использование Аннотации Android - это опция. Это позволит вам просто запустить любой метод в фоновом потоке:

// normal method
private void normal() {
    doSomething(); // do something in background
}

@Background
protected void doSomething() 
    // run your networking code here
}

Обратите внимание, что, хотя он обеспечивает преимущества простоты и удобочитаемости, у него есть свои недостатки.

3
задан Thanatos 23 March 2014 в 05:01
поделиться

4 ответа

Есть ряд проблем, которые я вижу:

  • 0x2d - системный вызов brk на x86 (32 бит); на x86_64 это 0xc
  • brk устанавливает конец сегмента данных; он возвращает 0 при успехе и -1 при сбое. Он не возвращает «первую позицию в куче». Это происходит от символа _end, который компоновщик устанавливает в конец неинициализированных предварительно распределенных данных.

Итак, вы хотите что-то вроде:

    mov [brk_firstloaction], _end
    mov rbx, [brk_firstlocation]
    add rbx, 0x14         ; space for 5 dwords (20 bytes)
    mov rax, 12
    int 0x80
1
ответ дан Chris Dodd 24 August 2018 в 20:03
поделиться

Как вы это сделали, вызовите один раз, чтобы извлечь текущее дно кучи, а затем переместите верхнюю часть кучи (что является значением brk). Однако ваш код неверен при использовании 64-битного набора регистров r.x. Если ваш Linux 32-разрядный (что подразумевается при использовании 45 для номера системного вызова), тогда вы хотите установить 32-битный регистр:

mov eax, 45                            ; brk                                                                                                                                                                                  
mov ebx, 0                             ; arg 1: 0 = fail returning brk value in rax                                                                                                                               
int 0x80                               ; syscall
mov dword ptr [brk_firstLocation], rax ; save result
mov eax, 45                            ; brk                                                                                                                                                                                  
mov ebx, 4                             ; arg 1: allocate 4 bytes for a 32-bit int                                                                                                                                
int 0x80                               ; syscall

mov eax, dword ptr [brk_firstLocation] ; reload rax with allocated memory address.
mov dword ptr [eax], 42 ; use result: store 42 in newly allocated storage

Конечно, вы можете повторно загрузить сохраненный значение для повторного использования столько раз, сколько необходимо.

0
ответ дан Gene 24 August 2018 в 20:03
поделиться

int 80h предназначен только для 32-битных системных вызовов. Вместо этого используйте syscall для 64 бит.

Вызов sys_brk дважды избыточен - в сборке вы всегда знаете, где заканчиваются ваши данные программы. Просто поместите там ярлык, и у вас будет адрес.

Выделяя таким образом память менее одной страницы, бессмысленно, она будет распределяться в блоках по 4 КБ в любом случае.

Важно понимать - sys_brk не является функцией управления кучей. Это низкоуровневое управление памятью.

2
ответ дан johnfound 24 August 2018 в 20:03
поделиться

другие указали несколько вещей, которые не соответствуют вашему коду. Я хотел бы добавить, что вы не добавили бы 20 бит к текущей точке останова (или 20 байтов , подобных add rbx, 20), вы просто добавили бы 5 байтов.

Кроме того, ваш первый аргумент syscall не будет в rbx, он будет в rdi. В 64-битном syscall ABI используются разные номера системных вызовов, разные регистры и другая команда (syscall вместо int 0x80), чем 32-разрядная ABI (которая по-прежнему доступна в 64- битных процессов). См. Также wiki wiki для дополнительных ссылок ABI.

Вот как выглядит ваш код:

push rbp
mov rbp, rsp

;; sys_brk(0)
mov   rax, 12         ; 12 is SYS_brk (/usr/include/asm/unistd_64.h)
mov   rdi, 0          ; rdi for first syscall arg in the 64-bit ABI, not rbx
syscall               ; syscall, not int 0x80, for the 64-bit ABI

mov   qword [brk_firstLocation], rax

;; sys_brk(old_break + 5)
lea   rdi, [rax + 5]  ; add 5 bytes to the break point
mov   rax, 12
syscall               ; set the new breakpoint

На этом этапе вы можете используйте brk_firstLocation как указатель на любую 5-байтовую структуру, которую вы хотите сохранить в куче. Вот как вы могли бы поместить значения в это пространство памяти:

mov   rdi, [brk_firstLocation]   ; load the pointer from memory, if you didn't already have it in a register

mov   byte [rdi], 'A'            ; a char at it's first byte
mov   [rdi+1], ecx               ; a 32-bit value in the last 4 bytes.
3
ответ дан Peter Cordes 24 August 2018 в 20:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: