[질문]malloc을 사용자정의 malloc으로 치환하는 데 생기는 에러

juluv의 이미지

안녕하세요. 요 며칠째 같은문제로 계속 고민하니 마음이 하도 답답하여 고수님들의 도움을 받고자 이렇게 글을 올리게 되었습니다.

먼저 제가 하고자 하는 것은 "malloc을 사용자정의 malloc으로 치환" 하는 것입니다. 이를 위해 http://uberhip.com/godber/interception/html/slide_6.html 에 있는 LD_PRELOAD 기법을 참조하여 저만의 동적 라이브러리를 만들고, 그것을 실행하여 보았습니다. 그러면 "segement falut"만이 계속 납니다. :cry:

저만의 malloc 부분에 대한 코드는 다음과 같습니다.

#include <stdio.h>
#include <stdlib.h>
#include <linux/unistd.h>
#include <errno.h>
#include <dlfcn.h>

void* malloc(size_t size)
{
	void *handle;
	void *(*orig_malloc)(size_t size);
	char *error;
	void *result;
	
	handle=dlopen("/lib/libc.so.6",RTLD_LAZY);
	if(!handle){
		fputs(dlerror(),stderr);
		exit(EXIT_FAILURE);
	}

	orig_malloc = dlsym(handle, "malloc");
	if((error=dlerror()) != NULL){
		fputs("error",stderr);
		exit(EXIT_FAILURE);
	}
	result = (*orig_malloc)(size);
	return result;
}

아낌없는 조언 부탁드립니다. 긴 글 읽어주셔서 감사합니다.

pynoos의 이미지

malloc이 불릴때마다 dlopen, dlsym이 일어나는 것 보다는,
orig_malloc 변수를 static으로 만들어 놓고,
NULL일 때(즉, 최초에만)만 dlopen dlsym 으로 할당하는 것이 좋을 것 같습니다.

그리고, malloc 뿐아니라, free 도 하신건가요? 그 쌍이 맞지 않으면, 두 함수간 사용하는 static 변수가 (혹시 있다면) 제대로 안될 것 같습니다만..

mach의 이미지

매번 느끼지만, pynoos님의 답변은 간결 명확하군요.

Quote:
가는 선, 정교한 생명시계.
오늘도 하루를 오차없는 프로그램처럼 살아 있다.

멋지십니다.

------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.

익명 사용자의 이미지

제가 만든거는 아니고,,,

vmware 의 메뉴를 숨기기 위해서 gtk_widget_show 를 치환하는 프로그램인데
관련있는 듯하여 올려 봅니다.

pynoos 님이 설명한 내용 그대로 입니다.

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <gtk/gtkwidget.h>

void gtk_widget_show(GtkWidget *widget) {
	static void (*next_gtk_widget_show)(GtkWidget*) = NULL;

	if (!next_gtk_widget_show) {
		next_gtk_widget_show = dlsym(RTLD_NEXT, "gtk_widget_show");
		if (!next_gtk_widget_show) {
			fprintf(stderr, "Abort: no gtk_widget_show\n");
			abort();
		}
	}

	if (widget && widget->name && widget->state == 0 && !strcmp(widget->name, "<main>")) {
		return;
	}
	next_gtk_widget_show(widget);
}

juluv의 이미지

지적 감사합니다. 일단 말씀해주신대로 저의 malloc루틴을 다음과 같이 수정하였습니다.

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>

void* malloc(size_t size)
{
	void *handle;
	static void *(*orig_malloc)(size_t size);
	char *error;
	void *result;
	
	if(!orig_malloc){
		handle=dlopen("/lib/libc.so.6",RTLD_LAZY);
		if(!handle){
			//fputs(dlerror(),stderr);
			exit(EXIT_FAILURE);
		}

		orig_malloc = dlsym(handle, "malloc");
		if((error=dlerror()) != NULL){
			//fputs("error",stderr);
			exit(EXIT_FAILURE);
		}	
	}
	result = (*orig_malloc)(size);
	return result;
}

이것을 다음과 같이 컴파일 하여 라이브러리를 생성하고...

#!/bin/sh
gcc -fPIC -rdynamic -g -c -Wall myalloc.c
gcc -shared -Wl,-soname,libmy.so.1 -o libmy.so.1.0.1 myalloc.o -lc -ldl
export LD_PRELOAD=./libmy.so.1.0.1

다음과 같은 프로그램에서 테스트하였습니다.

#include<stdio.h>
#include<stdlib.h>
int main()
{
    int *a=malloc(2);
    return 0;
}

결과는...

Quote:
Segmentation Fault

이네요..

free를 쓰지 않았더라도 오버라이딩시키기전의 malloc일때는 에러가 나지 않았는데요..
다시한번 도움을 주시면 감사하겠습니다.
안녕히 계세요.. 꾸벅..

juluv의 이미지

아무리 보아도 orig_malloc이 제대로 할당이 이루어지지 않는 것 같은데요..
1. 일단 orig_malloc에 값이 할당은 되는것 같습니다. 이 값이 NULL일때 무언가를 찍어보도록 추가를 해보았는데 그렇지 않았기 때문입니다.
2. 1의 추측대로다면 그 값이 제대로 되지 않은 것이라서 에러가 나는것 같다는 생각이 드네요.. :oops:
3. 2가 맞다면 다음 두부분중에 하나가 오작동한 것일텐데요..
handle=dlopen("/lib/libc.so.6",RTLD_LAZY);

orig_malloc=dlsym(handle,"malloc") 4. 3에서 혹시 "/lib/libc.so.6"이 잘못된 것은 아닐까요? :shock: libc.so.6 라이브러리에서 잘못된 handle을 주었다거나... :?:

이상 저의 허접한 추측이었습니다.. 어떤 지적도 감사히 받겠습니다.

익명 사용자의 이미지

일단 아래코트는 동작합니다.
google에서 malloc dlsym 정도로 검색하시면 많은 도움을 얻으실 수 있을
거라 생각합니다.

원인에 대해서는 대충 짐작이 가는데, 실력이 부족하여 제대로 설명이 안되는군요....

#define _GNU_SOURCE  
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <dlfcn.h>

void* malloc(size_t size)
{
	void *handle;
	static void *(*orig_malloc)(size_t size) = NULL;
	char *error;
	void *result;

	if(!orig_malloc){
		orig_malloc = dlsym(RTLD_NEXT, "malloc");
		if((error=dlerror()) != NULL){
			//fputs("error",stderr);
			exit(EXIT_FAILURE);
		}   
	}

	result = (*orig_malloc)(size);
	return result;
} 

The symbols RTLD_DEFAULT and RTLD_NEXT are defined by <dlfcn.h> only when _GNU_SOURCE was defined before including it.

kkojiband의 이미지

dlopen() 함수 자체가 malloc() 를 호출합니다. 그래서 님의 코드는 preload 된 malloc 이 재귀적으로 계속 호출되다가 fault 가 나는 것입니다. 그래서 위의 분이 얘기하신 대로 미리 할당되어있는 RTLD_NEXT 를 이용해서 malloc 을 받아야만 합니다...

이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~

juluv의 이미지

관심을 가져주신 분들 정말 감사드립니다.
나눔의 힘이 크다는 것을 다시한번 느끼게 되었습니다. 저도 능력이 되는 한 다른 분들께 도움이 될 수 있도록 열심히 하겠습니다.

다시한번 감사드립니다. :D

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.