2014.07.02 11:40

Declaring Attributes of Functions

In GNU C, you declare certain things about functions called in your program which help the compiler optimize function calls and check your code more carefully.

The keyword __attribute__ allows you to specify special attributes when making a declaration. This keyword is followed by an attribute specification inside double parentheses. The following attributes are currently defined for functions on all targets: noreturn,noinlinealways_inlinepureconstformatformat_argno_instrument_functionsectionconstructordestructorusedunuseddeprecatedweakmalloc, and alias. Several other attributes are defined for functions on particular target systems. Other attributes, includingsection are supported for variables declarations (see Variable Attributes) and for types (see Type Attributes).

You may also specify attributes with __ preceding and following each keyword. This allows you to use them in header files without being concerned about a possible macro of the same name. For example, you may use __noreturn__ instead of noreturn.

See Attribute Syntax, for details of the exact syntax for using attributes.

noreturn
A few standard library functions, such as abort and exit, cannot return. GCC knows this automatically. Some programs define their own functions that never return. You can declare them noreturn to tell the compiler this fact. For example,
          void fatal () __attribute__ ((noreturn));
          
          void
          fatal (...)
          {
            ... /* Print error message. */ ...
            exit (1);
          }
          

The noreturn keyword tells the compiler to assume that fatal cannot return. It can then optimize without regard to what would happen if fatal ever did return. This makes slightly better code. More importantly, it helps avoid spurious warnings of uninitialized variables.

Do not assume that registers saved by the calling function are restored before calling the noreturn function.

It does not make sense for a noreturn function to have a return type other than void.

The attribute noreturn is not implemented in GCC versions earlier than 2.5. An alternative way to declare that a function does not return, which works in the current version and in some older versions, is as follows:

          typedef void voidfn ();
          
          volatile voidfn fatal;
          

noinline
This function attribute prevents a function from being considered for inlining. 
always_inline
Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function even if no optimization level was specified. 
pure
Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the attribute pure. For example,
          int square (int) __attribute__ ((pure));
          

says that the hypothetical function square is safe to call fewer times than the program says.

Some of common examples of pure functions are strlen or memcmp. Interesting non-pure functions are functions with infinite loops or those depending on volatile memory or other system resource, that may change between two consecutive calls (such as feof in a multithreading environment).

The attribute pure is not implemented in GCC versions earlier than 2.96. 

const
Many functions do not examine any values except their arguments, and have no effects except the return value. Basically this is just slightly more strict class than the pure attribute above, since function is not allowed to read global memory.

Note that a function that has pointer arguments and examines the data pointed to must not be declared const. Likewise, a function that calls a non-const function usually must not be const. It does not make sense for a const function to return void.

The attribute const is not implemented in GCC versions earlier than 2.5. An alternative way to declare that a function has no side effects, which works in the current version and in some older versions, is as follows:

          typedef int intfn ();
          
          extern const intfn square;
          

This approach does not work in GNU C++ from 2.6.0 on, since the language specifies that the const must be attached to the return value. 

format (archetypestring-indexfirst-to-check)
The format attribute specifies that a function takes printfscanfstrftime or strfmon style arguments which should be type-checked against a format string. For example, the declaration:
          extern int
          my_printf (void *my_object, const char *my_format, ...)
                __attribute__ ((format (printf, 2, 3)));
          

causes the compiler to check the arguments in calls to my_printf for consistency with the printf style format string argument my_format.

The parameter archetype determines how the format string is interpreted, and should be printfscanfstrftime or strfmon. (You can also use __printf____scanf____strftime__ or __strfmon__.) The parameter string-index specifies which argument is the format string argument (starting from 1), while first-to-check is the number of the first argument to check against the format string. For functions where the arguments are not available to be checked (such as vprintf), specify the third parameter as zero. In this case the compiler only checks the format string for consistency. For strftime formats, the third parameter is required to be zero.

In the example above, the format string (my_format) is the second argument of the function my_print, and the arguments to check start with the third argument, so the correct parameters for the format attribute are 2 and 3.

The format attribute allows you to identify your own functions which take format strings as arguments, so that GCC can check the calls to these functions for errors. The compiler always (unless -ffreestanding is used) checks formats for the standard library functions printffprintfsprintfscanffscanfsscanfstrftimevprintfvfprintf and vsprintf whenever such warnings are requested (using -Wformat), so there is no need to modify the header file stdio.h. In C99 mode, the functions snprintf,vsnprintfvscanfvfscanf and vsscanf are also checked. Except in strictly conforming C standard modes, the X/Open function strfmon is also checked as are printf_unlocked and fprintf_unlocked. See Options Controlling C Dialect

format_arg (string-index)
The format_arg attribute specifies that a function takes a format string for a printfscanfstrftime or strfmon style function and modifies it (for example, to translate it into another language), so the result can be passed to a printfscanfstrftime or strfmonstyle function (with the remaining arguments to the format function the same as they would have been for the unmodified string). For example, the declaration:
          extern char *
          my_dgettext (char *my_domain, const char *my_format)
                __attribute__ ((format_arg (2)));
          

causes the compiler to check the arguments in calls to a printfscanfstrftime or strfmon type function, whose format string argument is a call to the my_dgettext function, for consistency with the format string argument my_format. If the format_arg attribute had not been specified, all the compiler could tell in such calls to format functions would be that the format string argument is not constant; this would generate a warning when -Wformat-nonliteral is used, but the calls could not be checked without the attribute.

The parameter string-index specifies which argument is the format string argument (starting from 1).

The format-arg attribute allows you to identify your own functions which modify format strings, so that GCC can check the calls to printfscanfstrftime or strfmon type function whose operands are a call to one of your own function. The compiler always treats gettextdgettext, and dcgettext in this manner except when strict ISO C support is requested by -ansi or an appropriate -std option, or -ffreestanding is used. See Options Controlling C Dialect

no_instrument_function
If -finstrument-functions is given, profiling function calls will be generated at entry and exit of most user-compiled functions. Functions with this attribute will not be so instrumented. 
section ("section-name")
Normally, the compiler places the code it generates in the text section. Sometimes, however, you need additional sections, or you need certain particular functions to appear in special sections. The section attribute specifies that a function lives in a particular section. For example, the declaration:
          extern void foobar (void) __attribute__ ((section ("bar")));
          

puts the function foobar in the bar section.

Some file formats do not support arbitrary sections so the section attribute is not available on all platforms. If you need to map the entire contents of a module to a particular section, consider using the facilities of the linker instead. 

constructor
destructor
The constructor attribute causes the function to be called automatically before execution enters main (). Similarly, the destructor attribute causes the function to be called automatically after main () has completed or exit () has been called. Functions with these attributes are useful for initializing data that will be used implicitly during the execution of the program.

These attributes are not currently implemented for Objective-C. 

unused
This attribute, attached to a function, means that the function is meant to be possibly unused. GCC will not produce a warning for this function. GNU C++ does not currently support this attribute as definitions without parameters are valid in C++. 
used
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly. 
deprecated
The deprecated attribute results in a warning if the function is used anywhere in the source file. This is useful when identifying functions that are expected to be removed in a future version of a program. The warning also includes the location of the declaration of the deprecated function, to enable users to easily find further information about why the function is deprecated, or what they should do instead. Note that the warnings only occurs for uses:
          int old_fn () __attribute__ ((deprecated));
          int old_fn ();
          int (*fn_ptr)() = old_fn;
          

results in a warning on line 3 but not line 2.

The deprecated attribute can also be used for variables and types (see Variable Attributes, see Type Attributes.) 

weak
The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions which can be overridden in user code, though it can also be used with non-function declarations. Weak symbols are supported for ELF targets, and also for a.out targets when using the GNU assembler and linker. 
malloc
The malloc attribute is used to tell the compiler that a function may be treated as if it were the malloc function. The compiler assumes that calls to malloc result in a pointers that cannot alias anything. This will often improve optimization. 
alias ("target")
The alias attribute causes the declaration to be emitted as an alias for another symbol, which must be specified. For instance,
          void __f () { /* do something */; }
          void f () __attribute__ ((weak, alias ("__f")));
          

declares f to be a weak alias for __f. In C++, the mangled name for the target must be used.

Not all target machines support this attribute. 

regparm (number)
On the Intel 386, the regparm attribute causes the compiler to pass up to number integer arguments in registers EAX, EDX, and ECX instead of on the stack. Functions that take a variable number of arguments will continue to be passed all of their arguments on the stack. 
stdcall
On the Intel 386, the stdcall attribute causes the compiler to assume that the called function will pop off the stack space used to pass arguments, unless it takes a variable number of arguments.

The PowerPC compiler for Windows NT currently ignores the stdcall attribute. 

cdecl
On the Intel 386, the cdecl attribute causes the compiler to assume that the calling function will pop off the stack space used to pass arguments. This is useful to override the effects of the -mrtd switch.

The PowerPC compiler for Windows NT currently ignores the cdecl attribute. 

longcall
On the RS/6000 and PowerPC, the longcall attribute causes the compiler to always call the function via a pointer, so that functions which reside further than 64 megabytes (67,108,864 bytes) from the current location can be called. 
long_call/short_call
This attribute allows to specify how to call a particular function on ARM. Both attributes override the -mlong-calls (see ARM Options) command line switch and #pragma long_calls settings. The long_call attribute causes the compiler to always call the function by first loading its address into a register and then using the contents of that register. The short_call attribute always places the offset to the function from the call site into the BL instruction directly. 
dllimport
On the PowerPC running Windows NT, the dllimport attribute causes the compiler to call the function via a global pointer to the function pointer that is set up by the Windows NT dll library. The pointer name is formed by combining __imp_ and the function name. 
dllexport
On the PowerPC running Windows NT, the dllexport attribute causes the compiler to provide a global pointer to the function pointer, so that it can be called with the dllimport attribute. The pointer name is formed by combining __imp_ and the function name. 
exception (except-func [, except-arg])
On the PowerPC running Windows NT, the exception attribute causes the compiler to modify the structured exception table entry it emits for the declared function. The string or identifier except-func is placed in the third entry of the structured exception table. It represents a function, which is called by the exception handling mechanism if an exception occurs. If it was specified, the string or identifier except-arg is placed in the fourth entry of the structured exception table. 
function_vector
Use this attribute on the H8/300 and H8/300H to indicate that the specified function should be called through the function vector. Calling a function through the function vector will reduce code size, however; the function vector has a limited size (maximum 128 entries on the H8/300 and 64 entries on the H8/300H) and shares space with the interrupt vector.

You must use GAS and GLD from GNU binutils version 2.7 or later for this attribute to work correctly. 

interrupt
Use this attribute on the ARM, AVR, M32R/D and Xstormy16 ports to indicate that the specified function is an interrupt handler. The compiler will generate function entry and exit sequences suitable for use in an interrupt handler when this attribute is present.

Note, interrupt handlers for the H8/300, H8/300H and SH processors can be specified via the interrupt_handler attribute.

Note, on the AVR interrupts will be enabled inside the function.

Note, for the ARM you can specify the kind of interrupt to be handled by adding an optional parameter to the interrupt attribute like this:

          void f () __attribute__ ((interrupt ("IRQ")));
          

Permissible values for this parameter are: IRQ, FIQ, SWI, ABORT and UNDEF. 

interrupt_handler
Use this attribute on the H8/300, H8/300H and SH to indicate that the specified function is an interrupt handler. The compiler will generate function entry and exit sequences suitable for use in an interrupt handler when this attribute is present. 
sp_switch
Use this attribute on the SH to indicate an interrupt_handler function should switch to an alternate stack. It expects a string argument that names a global variable holding the address of the alternate stack.
          void *alt_stack;
          void f () __attribute__ ((interrupt_handler,
                                    sp_switch ("alt_stack")));
          

trap_exit
Use this attribute on the SH for an interrupt_handle to return using trapa instead of rte. This attribute expects an integer argument specifying the trap number to be used. 
eightbit_data
Use this attribute on the H8/300 and H8/300H to indicate that the specified variable should be placed into the eight bit data section. The compiler will generate more efficient code for certain operations on data in the eight bit data area. Note the eight bit data area is limited to 256 bytes of data.

You must use GAS and GLD from GNU binutils version 2.7 or later for this attribute to work correctly. 

tiny_data
Use this attribute on the H8/300H to indicate that the specified variable should be placed into the tiny data section. The compiler will generate more efficient code for loads and stores on data in the tiny data section. Note the tiny data area is limited to slightly under 32kbytes of data. 
signal
Use this attribute on the AVR to indicate that the specified function is an signal handler. The compiler will generate function entry and exit sequences suitable for use in an signal handler when this attribute is present. Interrupts will be disabled inside function. 
naked
Use this attribute on the ARM or AVR ports to indicate that the specified function do not need prologue/epilogue sequences generated by the compiler. It is up to the programmer to provide these sequences. 
model (model-name)
Use this attribute on the M32R/D to set the addressability of an object, and the code generated for a function. The identifier model-name is one of smallmedium, or large, representing each of the code models.

Small model objects live in the lower 16MB of memory (so that their addresses can be loaded with the ld24 instruction), and are callable with the bl instruction.

Medium model objects may live anywhere in the 32-bit address space (the compiler will generate seth/add3 instructions to load their addresses), and are callable with the bl instruction.

Large model objects may live anywhere in the 32-bit address space (the compiler will generate seth/add3 instructions to load their addresses), and may not be reachable with the bl instruction (the compiler will generate the much slower seth/add3/jlinstruction sequence).

You can specify multiple attributes in a declaration by separating them by commas within the double parentheses or by immediately following an attribute declaration with another attribute declaration.

Some people object to the __attribute__ feature, suggesting that ISO C's #pragma should be used instead. At the time __attribute__ was designed, there were two reasons for not doing this.

  1. It is impossible to generate #pragma commands from a macro.
  2. There is no telling what the same #pragma might mean in another compiler.

These two reasons applied to almost any application that might have been proposed for #pragma. It was basically a mistake to use #pragma for anything.

The ISO C99 standard includes _Pragma, which now allows pragmas to be generated from macros. In addition, a #pragma GCC namespace is now in use for GCC-specific pragmas. However, it has been found convenient to use __attribute__ to achieve a natural attachment of attributes to their corresponding declarations, whereas #pragma GCC is of use for constructs that do not naturally form part of the grammar. See Miscellaneous Preprocessing Directives.

Posted by k1rha
2014.05.02 16:58

[ kernel ] 루트킷 분석하다가 조사한 커널 함수들.


Init_module : 커널함수의 시작은 main 대신 init_moudle 사용함.

IOCTL : read(), write() 와같이 읽기 쓰기 처리가 가능  -> 하드웨어의 제어나 상태를 얻기 위해 사용

Inet_add_protocol : 새로운 네트워크 프로토콜을 설정할수있음

Inet_del_protocol  : 기존 네트워크 프로토콜 삭제

create_proc_entry : proc 파일 시스템에서 접근   있는 파일을 만든다만들  있는 최상위 디렉토리는 /proc 이다. (구조체로 존재)

 

i_node 구조 (리눅스 디폴트 파일 시스템 ex2, ex3  채택)

  • i-mode : 파일의 속성  접근제어 정보 ( 정규파일 : S_IFREG , 디렉터리 : S_IFDIR , 장치파일 : S_IFCHR , 블록장치파일 : S_IFBLK , 파이프 : S_IFFIFO, 소켓 : S_IFSOCK

 

MODULE_PARM(char * modname, "s") // kernel 2.4 부터 insmod  인자를 받을  있도록 구성되었는데, s  문자열 형태를 받겠다는 

int gettimeofday(struct timeval *tv, struct timezone *tz);  :  timezone  설정함

copy_from_user(void * to, const void __user * from, unsigned long n)  :  사용자 메모리 블록 데이터를 커널 메모리 블록 데이터에  넣는다.

                                                                                             (from 사용자메모리, to 커널메모리)

 

nl->next = kmalloc(sizeof(struct nethide_list), GFP_KERNEL);

GFP_ATOMIC

메모리가 있으면 할당 없으면 NULL. 휴면 불가능

GFP_KERNEL

메모리 할당이 항상 성공하도록 요구, 메모리가 충분하지 않을 경우는 호출한 프로세스를 멈추고 동적 메모리 할당할 수 있는 상태가 될 때까지 대기. 휴면가능.

GFP_USER

유저 메모리를 할당함.  휴면 가능 

GFP_DMA

연속된 물리 메모리를 할당 받을 때 사용

 

 

즉, /dev/mem은 실제 물리 메모리, /dev/kmem은 커널 가상 메모리 공간에 접근할 수 있는 디바이스 파일입니다.

 

  • Hook, 우선순위1B Hook, 우선순위2C Hook, 우선순위 있을  nf_register_hook( D Hook, 우선순위2 ) 하면 아래처럼 
  • Hook, 우선순위1B Hook, 우선순위2 , D Hook, 우선순위,C Hook, 우선순위3

 

 

EXPORT_NO_SYMBOLS  :  전역 변수와 전역 함수를 커널 심볼 테이블에 등록해 놓음 ( 공개되지 않은 코드임 )

Dentry  ? : 해당 디렉토리가 포함하고 있는 디렉토리와 파일정보를 보유 하고 있음

 

 

Getdents()  Get directory entrys  : 디렉토리의 속성을 가져옴

query_module() : 함수를 이용해 커널 심볼 테이블과 커널에 적재된 다른 모듈의 심볼 테이블을 구한다이때 query_module() 함수에 QM_MODULES, QM_INFO, QM_SYMBOL 값을 지정하여 필요한 정보를 가져오는데, QM_MODULES는 커널에 포함된 모듈명을 얻어올 때 사용하며, QM_INFO는 각 모듈의 시작 주소와 크기를 얻기 위해 사용한다. 앞에서 구한 모듈 정보를 통해 QM_SYMBOL로 실질적인 커널 심볼 테이블과 커널에 적재된 다른 모듈의 심볼 테이블을 구한다

 

___this_module  : 현재 커널을 가리키고 있는 커널 내부 변수 

Ex)struct module *m = &__this_module;

 

Sysenter : sysenter가 호출되면 IA32_SYSENTER_EIP를 참고하여 KiFastCallEntry가 호출되는 것을 알 수 있었다.

커널 2.6 부터는 시스템 테이블을 그냥 오버라이딩   없기 때문에 나온 .

 

SSDT 후킹은 윈도우즈 API 가 커널 모드에서 서비스를 받기 위해 필요한 SSDT(System Service Descriptor Table) 의 내용을 조작하는 커널모드 후킹 방법 중에 하나 이다.

 

sysenter 명령은 유저모드에서 사용되는 명령어로, 현재 스레드가 유저모드에서 커널모드로 진입 시켜주는 역할을 한다. 인텔 메뉴얼에 보면 SYSENTER_EIP_MSR 가 가르키는 위치를 eip 레지스터에 넣어 실행 한다고 나와 있는데, 이 값은 MSRs(MODEL-SPECIFIC REGISTERS) 의 0x176 주소에서 가져온다. MSRs 는 rdmsr 명령으로 읽어올 수 있다.

 

IDT ( Interrupt Descriptor Table ) : 프로세서에서 인터럽트 혹은 exception  걸렸을 경우에 수행해야할 핸들러의 주소를 저장해 놓은것을 인터럽트 혹은 excetpion vector 라고 한다인텔 프로세서에서는 이러한 인터럽트 혹은 eception 핸들러들의 벡터와 벡터의 정보등을 저장해두는 구조체를 IDT 라고 부른다.

 

IDTR : 펜티엄에는 IDTR 이라 불리우는 특별한 레지스터가 존재한다 레지스터는 시스템의 IDT 존재하는 메모리 주소의베이스 어드레스와

IDT entry 의 개수가 저장되기로 약속된 레지스터 이다.

 

CPU 코어마다 IDTR 해당 IDTR 가리키는 IDT table   개수만큼 존재한다.

예를 들어 듀얼코어라면 IDTR 2개가 되고 IDT Table  두개가 된다그래서 보통 CPU 개수를 구해서 모든 IDT 조작하는 방식을 사용한다.

__asm sidt var : 해당 명령어를통해 var 변수에 IDT Entry[0] 번째 값이 들어간다.

__asm cli : 인텁트 발생 불가상태

__asm sti : 인터럽트 발생 가능 상태

 

rwlock_init : thread lock  읽고   있음

 

Kernel_thread  : 예전에 2.4.* 커널에서는 kernel_thread 함수을 직접 이용해서 thread 를 생성하고 스레드를 종료시킬때 complete을 이용해서 스레드 함수가 완전해 종료될때 까지 기다렸다가 모듈을 종료하였는데 2.6 의 현재 최신커널에서는 kthread을 사용하여 해서 위의 작업을 하는 함수가 만들어져 있다.

 

proc_dir_entry : 프로세스 디렉토리 속성값을 가지고 있는 커널 구조체

User_path_walk : it get the filename passed as argument and retrive the inode informations.. :)

lookup_dentry() : 파일 경로명을 가져온다그리고 엔트리 값을 반환한다.

GFP_KERNEL option으로 호출하면, kmalloc 당장은 메모리가 모잘라도 메모리가 생길 때까지 계속 try하는 반면에...

GFP_USER option으로 호출하면메모리 부족하면 대충 fail 끝나버리는 차이를 말하는 듯합니다.

inet_add_protocol() : 프로토콜 모듈 추가

 

nf_register_hook() 함수 : netfilter 후킹할때 사용하는데정확한 사전적 용어는 못찾음

 

init_mm은 mm_struct 라는 구조체로 이루어져 있는데 다음과 같다. 

mm_struct

위의 mm_struct 의 주석내용을 보면 다음과 같습니다. 

"owner"는 지금 mm struct의 user/owner인 정규(canonical) task를 가르켜야 한다.

init_task는 다음과 같다. 

 따라서 만약에 owner  바뀌기 위해서는 다음과 같은 과정이 행해져야 한다. 

현재 task  == mm->owner

현재 task의 mm != mm

새로운 task->mm = mm

새로운 task->alloc_lock 이 잠겨있어야 owner가 바뀔 수 있다.


Posted by k1rha
2014.04.24 21:07

ASLR 걸린 취약한 함수 테스트 하려다가 자주 쓰게 되는데 저장할 공간이 없어서 저장함


KEYWORD : LINUX dynamic 하게 library 호출 , 라이브러리 동적 호출, 동적으로 라이브러리 호출 , dlopen dlsym dlfcn.h ..


root@k1rh4:~/strcp# ls

strcpy2.c  test.c

root@k1rh4:~/strcp# gcc -g -c -fPIC strcpy2.c

root@k1rh4:~/strcp# ls

strcpy2.c  strcpy2.o  test.c

root@k1rh4:~/strcp# gcc -shared -lc -o libstrcpy2_so.so strcpy2.o

root@k1rh4:~/strcp# ls

libstrcpy2_so.so  strcpy2.c  strcpy2.o  test.c

root@k1rh4:~/strcp# gcc -o test test.c -ldl

-------------------------------------------------------------------------

root@k1rh4:~/strcp# cat test.c

#include<stdio.h>

#include<dlfcn.h>

#include<string.h>



int main(int argc, char *argv[]){


        char buff[100]="";


        void * lib_handle=NULL;

        int (*func)(char *, char *);


        func =NULL;


        lib_handle = dlopen("./libstrcpy2_so.so",RTLD_NOW);



        if(!lib_handle){

                printf("dlopen failed [ %s ] \n",dlerror());


                return 0;


        }



        func = dlsym(lib_handle,"strcpy2");

        func(buff,argv[1]);


        printf("[%s]\n\n",buff);


        if(!func){


                printf("dsym failed [%s ] \n ", dlerror());

        }

        dlclose(lib_handle);





return 0;

}

---------------------------------------------------------------------

root@k1rh4:~/strcp# cat strcpy2.c

#include<stdio.h>

#include<string.h>

int strcpy2(char *v1 ,char *v2){


        strcpy(v1, v2);

return  strlen(v2);

}


root@k1rh4:~/strcp#



* 공유 라이브러리 작성 컴파일 지식

gcc -fPIC -c <sorce file>
-fPIC : 위치와 관계없이 수행할 수 있는 코드로 컴파일

gcc -shared -Wl,-soname,appsolute.so.0 -o libapplib.so.0.0.0 <object files>
-shared : 공유 라이브러리로 생성
-Wl : 콤마로 구분된 옵션을 링커로 전달
-soname : 로더가 식별하는 라이브러리 이름
-o : 결과로 만들 파일이름

여기서 로더가 인식하는 이름과 실제 파일이름이 다를 수 있다.
그리고 여기서 만들고자 하는 링킹 형태는 다음과 같다.
gcc -o test test.cc -L<library path> -lappsolute
이에 심볼릭 링크를 생성하여 링커에게 이름과 실제 파일을 연결시킨다.

# 컴파일 시 -lappsolute 를 주면 링커는 libappsolute.so 를 찾는다. 따라서 libappsolute.so 를 생성한다
ln -s libapplib.so.0.0.0 libappsolute.so
# 컴파일 후 실행 파일을 실행할 경우 appsolute.so.<Version> 을 탐색한다
ln -s libapplib.so.0.0.0 appsolute.so.0
해당 링크를 추가한 후 아래 파일을 수정하여 라이브러리 경로를 추가한다.
/etc/ld.so.conf
경로 추가 후 적용
ldconfig


Posted by k1rha