Чтение счетчика команд непосредственно

После небольшого исследования я считаю, что проблема заключалась в том, что прокси на сервере закрывал соединение после нескольких минут простоя, и клиент ManagedChannel не обнаружил это автоматически и снова подключился, когда это произошло. При создании ManagedChannel я добавил к нему idleTimeout, который будет предварительно уничтожать соединение, когда оно бездействует, и восстанавливать его, когда оно понадобится снова, и это, похоже, решает проблему. Таким образом, новая конструкция канала выглядит следующим образом:

@Singleton
@Provides
fun providesMyClient(app: Application): MyClient {
    val channel = AndroidChannelBuilder
            .forAddress("example.com", 443)
            .overrideAuthority("example.com")
            .context(app.applicationContext)
            .idleTimeout(60, TimeUnit.SECONDS)
            .build()
    return MyClient(channel)
}
29
задан Peter Cordes 19 November 2017 в 21:36
поделиться

5 ответов

Нет, EIP / к IP нельзя получить доступ непосредственно, но в позиционно-зависимом коде это - разовая ссылкой константа, таким образом, можно использовать соседнее (или удаленный) символ как непосредственное.

   mov eax, nearby_label    ; in position-dependent code
nearby_label:
<час>

Для получения EIP или IP в позиционно-независимом 32-битном коде:

        call _here
_here:  pop eax
; eax now holds the PC.

На центральных процессорах, более новых, чем Pentium Pro (или PIII, вероятно), call rel32 с rel32=0, является специальным в корпусе для не влияния на стопку предиктора обратного адреса . Таким образом, это эффективно, а также компактно на современном x86 и - то, что лязг использует для 32-разрядного позиционно-независимого кода.

На старых 32-разрядных центральных процессорах Pentium Pro, это разбалансировало бы стопку предиктора вызова/возврата, поэтому предпочло бы вызывать функцию, которая действительно на самом деле возвращается, для предотвращения ответвления mispredicts максимум на приблизительно 15 будущем ret инструкции в родительских функциях. (Если Вы не собираетесь возвращаться, или так редко, что это не имеет значения.) Стопка предикторов обратного адреса восстановится, все же.

get_retaddr_ppro:
    mov  eax, [esp]
    ret                ; keeps the return-address predictor stack balanced
                       ; even on CPUs where  call +0 isn't a no-op.
<час>

В x86-64 режиме, RIP может быть считан непосредственно с помощью родственника RIP lea .

default rel           ; NASM directive: use RIP-relative by default

lea  rax, [_here]     ; RIP + 0
_here:

MASM или GNU .intel_syntax: lea rax, [rip]

AT& T синтаксис: lea 0(%rip), %rax

35
ответ дан Peter Cordes 28 November 2019 в 00:49
поделиться

Если вам нужен адрес конкретной инструкции, обычно что-то вроде этого делает свое дело:

thisone: 
   mov (e)ax,thisone

(Примечание: на некоторых ассемблерах это может сделать неправильно и прочитать слово из [thisone] , но обычно есть некоторый синтаксис для того, чтобы ассемблер делал правильные вещи.)

Если ваш код статически загружается по определенному адресу, ассемблер уже знает (если вы указали правильный начальный адрес) абсолютный адреса всех инструкций. Динамически загружаемый код, скажем, как часть приложения в любой современной ОС, получит правильный адрес благодаря перемещению адресов, выполняемому динамическим компоновщиком (при условии, что ассемблер достаточно умен, чтобы генерировать таблицы перемещения, которыми они обычно являются). 113]

27
ответ дан TrayMan 28 November 2019 в 00:49
поделиться

Нет никакой инструкции непосредственно считать указатель команд (EIP) на x86. Можно получить адрес текущей команды, собираемой с небольшим встроенным ассемблерным кодом:

// GCC inline assembler; for MSVC, syntax is different
uint32_t eip;
__asm__ __volatile__("movl $., %0", : "=r"(eip));

. ассемблерная директива заменяется адресом текущей команды ассемблером. Обратите внимание, что при обертывании вышеупомянутого отрывка в вызов функции Вы просто получите тот же адрес (в той функции) каждый раз. Если Вы хотите более применимую функцию C, можно вместо этого использовать некоторый невстроенный ассемблерный код:

// In a C header file:
uint32_t get_eip(void);

// In a separate assembly (.S) file:
.globl _get_eip
_get_eip:
    mov 0(%esp), %eax
    ret

Это означает каждый раз, когда Вы хотите получить указатель команд, это немного менее эффективно, так как Вам нужен дополнительный вызов функции. Обратите внимание, что, делая его этот путь не уносит стопку обратного адреса (RAS). Стопка обратного адреса является отдельной стопкой обратных адресов, используемых внутренне процессором для упрощения целевой прогноз ответвления для инструкций RET.

Каждый раз, когда у Вас есть Команда вызова, текущий EIP продвинут на RAS, и каждый раз, когда у Вас есть инструкция RET, RAS выталкивается, и главное значение используется в качестве целевого прогноза ответвления для той инструкции. Если Вы портите RAS (такой как, не соответствуя каждому ВЫЗОВУ RET, как в решение Cody), Вы собираетесь получить целый набор ненужного ответвления mispredictions, замедляя Вашу программу. Этот метод не уносит RAS, так как он имеет подобранную пару инструкций RET и ВЫЗОВА.

8
ответ дан Community 28 November 2019 в 00:49
поделиться

Существует независимый от архитектуры (но зависящий от gcc) способ доступа к адресу, который выполняется с использованием меток в качестве значений:

http://gcc.gnu.org/onlinedocs/gcc /Labels-as-Values.html

void foo()
{
  void *current_address = $current_address_label;
  current_address_label:
      ....
}
3
ответ дан Fons 28 November 2019 в 00:49
поделиться

На x86-64 вы можете сделать, например:

lea rax,[rip] (48 8d 05 00 00 00 00)
15
ответ дан 28 November 2019 в 00:49
поделиться
Другие вопросы по тегам:

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