通過(guò) __attribute( (section(x)) ) 來(lái)對(duì)函數(shù)進(jìn)行快速測(cè)試

通過(guò) __attribute( (section(x)) ) 來(lái)對(duì)函數(shù)進(jìn)行快速測(cè)試

先從簡(jiǎn)單代碼開始毫炉,以下代碼通過(guò)宏 EXPORT 來(lái)幫助我們快速定義一個(gè) myfun_t 變量, 所以在EXPORT(hello);就定義了一個(gè) _hello 變量, 于是我們可以在 main 中進(jìn)行訪問(wèn)

#include <stdio.h>

typedef struct
{
    void (*fun)(void);
    const char *desc;
} myfun_t;

#define EXPORT(x)               \
    static myfun_t _##x = {     \
        .fun = x                \
    }

void hello(void)
{
    printf("Hello\n");
}
EXPORT(hello);

int main(int argc, char const *argv[])
{
    _hello.fun();

    return 0;
}

__attribute 宏用來(lái)設(shè)置編譯屬性, __attribute( (section(x)) ) 可以指定編譯器將變量存放到指定的內(nèi)存區(qū)域, 之后我們就可以使用

extern type_t __start_<section_name>
extern type_t __stop_<section_name>

來(lái)進(jìn)行訪問(wèn), __start_<section_name> 代表段的起始, 是一個(gè)內(nèi)置標(biāo)簽, 就像 int a = 12; 中的 a 一樣, 它的數(shù)據(jù)類型取決于我們?nèi)绾慰创? 和很多變量標(biāo)簽一樣, 通過(guò) & 可以訪問(wèn)變量所在的地址, 所以訪問(wèn)段的的起始地址為 &__start_mysection

#include <stdio.h>

#define MYSECTION __attribute((used, section("mysection")))

char mystr[] MYSECTION = "Good";
// int myvalue MYSECTION = 125;

int main(int argc, char const *argv[])
{
    extern char __start_mysection;
    printf("%s\n", &__start_mysection);
    
    // extern int __start_mysection;
    // printf("%d\n", myvalue);     // 125

    return 0;
}

測(cè)試代碼

有了上面的基礎(chǔ), 就可以嘗試寫快速測(cè)試的代碼了,一般來(lái)說(shuō)我們希望快速測(cè)試一個(gè)函數(shù), 編寫完后在函數(shù)下面通過(guò)一個(gè)宏定義 TEST_FUNC_ADD 就可以將函數(shù)插入到測(cè)試代碼的行列。

test.h

#pragma once

typedef struct
{
    void (*fun)(void);
    const char *name;
    const char *desc;
    char _tmp[8]; /* 32 位對(duì)齊 */
} test_command_t;

#define SECTION __attribute((used, section("myfun_section")))

#define EXPORT_TEST_COMMAND(f, n, d)       \
    static test_command_t _##f SECTION = { \
        .fun = f,                          \
        .name = n,                         \
        .desc = d,                         \
    }

#define TEST_FUNC_ADD(f, n, d, ...)           \
    static void _##f(void)                    \
    {                                         \
        int r = f(__VA_ARGS__);               \
        if (r == 0)                           \
            printf("Func %s TEST OK\n", n);   \
        else                                  \
            printf("%s TEST ERR %d\n", n, r); \
        return;                               \
    }                                         \
    EXPORT_TEST_COMMAND(_##f, n, d)

test.c

#include "test.h"
#include <stdio.h>
#include <string.h>

/* 獲取函數(shù)列表所在的內(nèi)存區(qū)間 */
extern test_command_t __start_myfun_section;
extern test_command_t __stop_myfun_section;
test_command_t *myfun_section_begin = &__start_myfun_section;
test_command_t *myfun_section_end = &__stop_myfun_section;

#define foreach_command(item) \
    for (test_command_t *item = myfun_section_begin; \
    item != myfun_section_end; item++)

void func1(void)
{
    printf("func1: hello\n");
}
EXPORT_TEST_COMMAND(func1, "print", "To print hello");

int func_test(int max)
{
    if (max < 10)
        return 0;

    return -1;
}
TEST_FUNC_ADD(func_test, "less", "Check less than 10", 8);

int main(int argc, char const *argv[])
{
    char command[256];

    while (1)
    {
        printf("\nsh# ");
        gets(command);

        if (strncmp(command, "help", 4) == 0)
        {
            foreach_command(entry)
            {
                printf("    %-15s\t -- %s\n", entry->name, entry->desc);
            }

            continue;
        }

        foreach_command(entry)
        {
            if (strcmp(entry->name, command) == 0)
            {
                entry->fun();
                break;
            }
        }
    }

    return 0;
}

然而上述功能只能對(duì) GCC 平臺(tái)有效, 如果是 ARMCC 或是其他平臺(tái), 因?yàn)榫幾g器不同, 方法可能不一樣, 為了跨平臺(tái), 就不得不添加平臺(tái)檢測(cè)的宏, 比如將下面的代碼替換獲取 myfun_section 所在的內(nèi)存區(qū)間部分即可支持 ARMCC 平臺(tái)溜在。

#ifdef __ARMCC_VERSION  /* ARM C Compiler */
    extern test_command_t myfun_section$$Base;
    extern test_command_t myfun_section$$Limit;
    test_command_t *myfun_section_begin = &(myfun_section$$Base);
    test_command_t *myfun_section_end = &(myfun_section$$Limit);
#elif defined (__GNUC__)
    extern test_command_t __start_myfun_section;
    extern test_command_t __stop_myfun_section;
    test_command_t *myfun_section_begin = &__start_myfun_section;
    test_command_t *myfun_section_end = &__stop_myfun_section;
#else
    #error "The platform is not supported"
#endif

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌筑煮,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粤蝎,死亡現(xiàn)場(chǎng)離奇詭異真仲,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)诽里,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門袒餐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)飞蛹,“玉大人谤狡,你說(shuō)我怎么就攤上這事∥蚤埽” “怎么了墓懂?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)霉囚。 經(jīng)常有香客問(wèn)我捕仔,道長(zhǎng),這世上最難降的妖魔是什么盈罐? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任榜跌,我火速辦了婚禮,結(jié)果婚禮上盅粪,老公的妹妹穿的比我還像新娘钓葫。我一直安慰自己,他們只是感情好票顾,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布础浮。 她就那樣靜靜地躺著帆调,像睡著了一般。 火紅的嫁衣襯著肌膚如雪豆同。 梳的紋絲不亂的頭發(fā)上番刊,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音影锈,去河邊找鬼芹务。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鸭廷,可吹牛的內(nèi)容都是我干的锄禽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼靴姿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼沃但!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起佛吓,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤宵晚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后维雇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體淤刃,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年吱型,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逸贾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡津滞,死狀恐怖铝侵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情触徐,我是刑警寧澤咪鲜,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站撞鹉,受9級(jí)特大地震影響疟丙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鸟雏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一享郊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孝鹊,春花似錦炊琉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)玄货。三九已至,卻和暖如春悼泌,著一層夾襖步出監(jiān)牢的瞬間松捉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工馆里, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留隘世,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓鸠踪,卻偏偏與公主長(zhǎng)得像丙者,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子营密,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345