Применяется ли стандартная «последовательность вызова функций», описанная в спецификациях Sys V ABI (i386 и AMD64), к статическим функциям C? - PullRequest
0 голосов
/ 28 декабря 2018

В компьютерном программном обеспечении двоичный интерфейс приложения (ABI) представляет собой интерфейс между двумя двоичными программными модулями;часто один из этих модулей представляет собой библиотеку или средство операционной системы, а другой - программу, запускаемую пользователем.

ABI определяет, как структуры данных или вычислительные процедуры доступны в машинном коде, которыйнизкоуровневый аппаратно-зависимый формат;напротив, API определяет этот доступ в исходном коде, который является относительно высокоуровневым, относительно аппаратно-независимым, часто читаемым человеком форматом.Общим аспектом ABI является соглашение о вызовах, которое определяет, как данные предоставляются как входные данные или читаются как выходные данные вычислительных процедур;примерами являются соглашения о вызовах x86.

- https://en.wikipedia.org/wiki/Application_binary_interface

Я уверен, что стандартная «последовательность вызова функций» описана в спецификации Sys V ABI (как для i386, так и для AMD64)ограничивает вызов этих внешних функций в библиотеке C, но ограничивает ли он также вызов этих статических функций?

Вот пример:

$cat abi.c

#include<stdio.h>
typedef void (*ret_function_t)(int,int);
ret_function_t gl_fp = NULL;
static void prnt(int i, int j){
    printf("hi from static prnt:%d:%d\n", i, j);
}
void api_1(int i){
    gl_fp = prnt;
    printf("hi from extern api_1:%d\n", i);
}
ret_function_t api_2(void){
    return gl_fp;
}

$cat abi_main.c

#include<stdio.h>
typedef void (*ret_function_t)(int,int);
extern void api_1(int i);
extern ret_function_t api_2(void);

int main(){
    api_1(1111);
    api_2()(2222, 3333);
}

$gcc abi_main.c abi.c -o abi_test

$./abi_test
hi from extern api_1:1111
hi from static prnt:2222:3333

Последовательность вызова функции (включаяиспользование регистров, кадр стека, передача параметров, переменные аргументы ...) детали определяются в ABI Sys V, когда abi_main.c вызывает api_1 и api_2, так как они являются внешними, но как насчет вызова статической функции prnt, котораябыл определен в abi.c?Относится ли он к стандарту ABI или к компилятору?

1 Ответ

0 голосов
/ 05 января 2019

Да, они применяются.Статические функции - это просто простые функции с видимостью единиц измерения.ABI - это задача генерации компилятора, стандарт C специально об этом ничего не говорит.Это становится понятным при удалении слова static из вашего кода.Аргументация та же.Недостаток при таком подходе заключается в том, что компилятор не может проверить право связи (вызывающий-вызываемый), а только его тип (void (*ret_function_t)(int,int);) во время компиляции, поскольку вы тот, кто ссылается во время выполнения.Таким образом, это не рекомендуется.

В результате ваш компилятор сгенерирует код для любой вызывающей функции, следуя некоторому ABI, и назовем его ABI-a.И он сгенерирует код для функции, вызываемой согласно некоторому другому ABI, скажем, ABI-b.Если ABI-a == ABI-b , это всегда работает, и это так, если вы компилируете оба файла с одинаковым ABI.

Например, это работает, если prntФункция была расположена по адресу 0x12345678:

ret_function_t gl_fp = (ret_function_t)0x12345678;

. Она также работает, пока есть функция с правильными аргументами в 0x12345678.Как видите, функция не может быть inline d, поскольку компилятор не знает, какое определение функции окажется в этой области памяти, их может быть много.

...