Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1213763
  • 博文数量: 404
  • 博客积分: 10011
  • 博客等级: 上将
  • 技术积分: 5382
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-03 16:29
文章存档

2010年(40)

2009年(140)

2008年(224)

我的朋友

分类: LINUX

2009-01-06 13:51:54

ifdef DJDIR
USING_DJGPP=1
endif
CFLAGS = -g
CC = gcc
# TESTS = 1 2 3 4 5 6 7 8 9
TEST_BASENAMES = $(basename $(wildcard test*.c))
#TEST_BASENAMES = $(basename $(wildcard *.c))
ifneq ($(USING_DJGPP),1)
all :  $(addsuffix .dynamic,$(TEST_BASENAMES)) \
 $(addsuffix .static,$(TEST_BASENAMES))
else
all : $(addsuffix .exe,$(TEST_BASENAMES))
endif
.PRECIOUS : %.o
%.o : %.c
 $(CC) $(CFLAGS) -c $<

%.dynamic : %.o main.o
 $(CC) -o $@ $^
%.static : %.o main.o ../libyamd.a ../yamd-gcc
 ../yamd-gcc -L.. -o $@ $< main.o
%.exe : %.o main.o ../libyamd.a
 ../yamd-gcc -L.. -o $@ $< main.o
clean :
 rm -f *.o *.static *.dynamic *.exe
 
 
    执行该Makefile后,可以看到输出信息:

YAMDMake Test

zwy:/home/yc/test/yamd-0.32# make test

make -C tests

make[1]: Entering directory `/home/yc/test/yamd-0.32/tests'

gcc -g -c test1.c

gcc -g -c main.c

gcc -o test1.dynamic test1.o main.o

gcc -g -c test10.c

gcc -o test10.dynamic test10.o main.o

gcc -g -c test11.c

gcc -o test11.dynamic test11.o main.o

gcc -g -c test12.c

gcc -o test12.dynamic test12.o main.o

gcc -g -c test13.c

gcc -o test13.dynamic test13.o main.o

gcc -g -c test14.c

gcc -o test14.dynamic test14.o main.o

gcc -g -c test15.c

gcc -o test15.dynamic test15.o main.o

gcc -g -c test2.c

gcc -o test2.dynamic test2.o main.o

gcc -g -c test3.c

gcc -o test3.dynamic test3.o main.o

gcc -g -c test4.c

gcc -o test4.dynamic test4.o main.o

gcc -g -c test5.c

gcc -o test5.dynamic test5.o main.o

gcc -g -c test6.c

gcc -o test6.dynamic test6.o main.o

gcc -g -c test7.c

gcc -o test7.dynamic test7.o main.o

gcc -g -c test8.c

gcc -o test8.dynamic test8.o main.o

gcc -g -c test9.c

gcc -o test9.dynamic test9.o main.o

 

上述说明:

动态的执行文件(test*.dynamic)就是使用gcc编译的(将main.otest*.c链接起来)

 

../yamd-gcc -L.. -o test1.static test1.o main.o

../yamd-gcc -L.. -o test10.static test10.o main.o

../yamd-gcc -L.. -o test11.static test11.o main.o

../yamd-gcc -L.. -o test12.static test12.o main.o

../yamd-gcc -L.. -o test13.static test13.o main.o

../yamd-gcc -L.. -o test14.static test14.o main.o

../yamd-gcc -L.. -o test15.static test15.o main.o

../yamd-gcc -L.. -o test2.static test2.o main.o

../yamd-gcc -L.. -o test3.static test3.o main.o

../yamd-gcc -L.. -o test4.static test4.o main.o

../yamd-gcc -L.. -o test5.static test5.o main.o

../yamd-gcc -L.. -o test6.static test6.o main.o

../yamd-gcc -L.. -o test7.static test7.o main.o

../yamd-gcc -L.. -o test8.static test8.o main.o

../yamd-gcc -L.. -o test9.static test9.o main.o

上述说明:

静态的可执行文件(test*.static)是采用yamd-gcc进行编译的,使用  L..  链接了上级目录(安装包目录)中的库文件( libyamd.a或libyamd-dynamic.so或libyamdf.a)

因为YAMD安装是也有库被安装到/usr/local/lib下,查看有如下库:

 libyamd.a      libyamd-dynamic.so       libyamdf.a

故上述库都有用,需要具体确定。

 

 

使用方法:

(1)使用编译器yamd-gcc

(2)加上-g,链接调试信息。

(3)运行可执行文件

 

run-yamd的使用:(注释README)

YAMD, Yet Another Malloc Debugger

 

By Nate Eldredge,

 

Overview

--------

 

YAMD is Yet Another Malloc Debugger.  It's a package to help in

finding bugs related to dynamic memory allocation.(动态内存分配问题)  At present, it

works under Linux/x86 and DJGPP(工作平台).  It provides several features not

found in most other such packages.

 

It can be found at ~neldredge/yamd/.

 

Features

--------

 

* YAMD uses the processor's paging mechanisms to enforce the

  boundaries of allocated blocks.  This means that:

   

    - Attempts to both read and write out of bounds(越界)will be trapped(捕获).

 

    - Traps will occur on the instruction that caused the bad access,

      rather than at some later time.  This makes it easier to find

      the culprit.

 

* Each operation is logged, not just with file and line number, but

  with a complete traceback.  This is especially helpful if most of

  your memory allocation is done through a few common functions.

 

* YAMD emulates `malloc' and friends at a very low level, meaning that

  indirect `malloc' calls from other library functions (like `strdup')

  are caught as well.  This also catches C++'s `new' and `delete'.

 

* No changes whatever are needed to your source.  Under Linux, dynamic

  loading of YAMD is supported, in which case you may not even need to

  re-link the program.

 

* Of course, it does all the usual checks you'd expect from a malloc

  debugger: checking for multiple freeing, memory leaks, etc.

 

 

Requirements

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

系统使用组件要求

Under Linux, you need a recent version of Binutils; 2.8 should work.

Also, you will get much better results if you have glibc 2.1 and a

recent (late 2.1 or 2.2) kernel.  Most features will still work with

earlier ones, though, including libc 5; but see "Caveats" below.

 

Under DJGPP, YAMD will only work if you run under plain DOS with

CWSDPMI as your DPMI server.  Most other DPMI servers only implement

the DPMI 0.9 spec, which lacks some vital features.  386MAX may work;

I haven't tried it.  Also, some problems in the debuggers can make

debugging awkward without special patches; see "Caveats".  Patched

debuggers are available at

 

You should have GCC, Make, Textutils, Fileutils, and Sed installed.

 

For either system, you will need a large amount of virtual memory

available.  Swap is fine.  Running YAMD on GCC compiling one of its

own large source files with -O2 required some 130MB of virtual memory

just for that process!  (This is because of the (necessarily) highly

inefficient allocation scheme.)

 

Installing

----------

 

Unpack the archive.  Obviously you've done that or you wouldn't be

reading this.

 

The default installation directory is /usr/local on Unix, and your

DJGPP directory on DJGPP.  Edit the Makefile if you want to change

this.

 

I have tested YAMD with GCC 2.95.1 and it works, so previous warnings

about this version probably do not apply.  The code looks to be OK

with respect to aliasing problems.

 

Run `make' to compile.  `make test' will compile some sample programs

in the `tests' subdirectory.  Just now there is no formal testsuite,

but each prints what it should do when it runs with YAMD.  You can

also look at them to see the sort of errors caught.

 

Get the appropriate permissions and run `make install'.

 

 

Compiling your programs(具体使用方法说明)

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

 

Some special considerations are needed in compiling to take advantage

of YAMD.

 

YAMD linked statically:(静态链接)

(1)      使用  -g  选项。

(2)      不能使用选项  -fomit-frame-pointer

(3)      使用  yamd-gcc  代替编译器  gcc  gxx  or  g++同理)。

(4)      linking   或者  strip the binary时不要使用  -s  选项。

 

 

     Use `-g' when compiling, and do not use `-fomit-frame-pointer'.

     When linking, replace `gcc' with `yamd-gcc' and similarly with

     `gxx' or `g++'.  (These names are based on what you specified as

     CC and CXX in the Makefile.)  Do not use `-s' when linking or

     strip the binary.

 

     NOTE: YAMD can no longer be disabled when compiled in.  This is

     an unfortunate but necessary side-effect of some other bugfixes.

     Thus, you should not compile YAMD into production binaries.

 

YAMD linked dynamically: (动态链接——与普通编译没有区别,只是参数选项的限制)

(1)      不使用下列选项 -s -fomit-frame-pointer

(2)      使用选项  -g

 

 

     Use `-g', not `-fomit-frame-pointer' or `-s'.  If your binary was

     originally built like this, you need not rebuild it.

 

 

Running your program and controlling YAMD

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

 

With the `run-yamd' shell script:

===========================================================

 

Syntax: run-yamd [options] program args...

 

例如:run-yamd -r /home/yc/test/yamd-0.32/tests/test

 

Note: `program' should be the path to your program; do not rely on

PATH being searched, because it isn't.

 

On DJGPP, you'll need to have bash and shell-utils installed, and run

bash explicitly.  So:

 

bash run-yamd [options] program args...

 

And use forward slashes for specifying `program'.

 

Options:

        

  -r : When corrupted magic bytes are found, fix ("repair") them after

   reporting to prevent further reports.  Default is to leave them.

 

  -d : If corrupted magic bytes are found, abort the program after

   reporting ("die").  Default is to continue.

 

  -f : Check the front (prefix) of blocks, instead of the end.  This

   is useful for catching negative overruns.

 

  -a nnn : Set default alignment of allocated blocks for which

   alignment is not specified (as with `memalign').  Must be a power

   of 2, and should be as small as possible to catch the most bugs.

   Default is 1, which provides the best checking, and is also faster

   (it avoids a lot of manual overrun checking).  The unaligned memory

   accesses have not proven to be a problem.

 

  -o file : Direct the log output to `file'.  Default is stderr.

 

  -l n : Set the minimum log level to n.  1 is INFO, 2 is WARNING, 3

   is ERROR.

 

  -s : Inform run-yamd that the program in question has YAMD

   statically linked with it, to prevent it from loading it

   dynamically (which is the default).

 

  -i : When loading YAMD dynamically, have other programs exec'd by

   the child inherit YAMD.  This is not well tested and may fail if

   the grandchildren were linked against a different libc version, for

   instance.

 

  -c file : Specify the YAMD shared object file.  Default is

   LIBDIR/libyamd-dynamic.so.

 

  -n : Omit the step which symifies the log (it can be slow).  This is

   probably not useful except for testing.

 

  -v : Print version and exit.

 

  -h : Print short help message and exit.

 

With environment variables:

===========================

 

Internally, YAMD is controlled by some environment variables; run-yamd

just sets them for you.  You can also set them yourself when

necessary.  FLAGS should be set to "0" or "1".

 

  YAMD_ENABLE (flag) : It is no longer necessary to set this variable.

 

  YAMD_REPAIR_CORRUPTED (flag) : Corresponds to -r option.

 

  YAMD_DIE_ON_CORRUPTED (flag) : Corresponds to -d option.

 

  YAMD_CHECK_FRONT (flag) : Corresponds to -f option.

 

  YAMD_DEFAULT_ALIGNMENT : Corresponds to -a option.

 

  YAMD_LOGLEVEL : Corresponds to -l option.

 

  YAMD_LOGFILE : Name of the file to which log output should be

  written.  Note that symification must be done manually.

 

  YAMD_LOGFILE_NAME : Same as above, for compatibility.

 

  LD_PRELOAD : On Linux, if YAMD should be dynamically loaded, this

  variable must include the YAMD shared object name.

 

  YAMD_CHILD_LD_PRELOAD : Value of LD_PRELOAD to pass to new

  processes.  Unless you want them to inherit YAMD (see -i), this

  should be the value of LD_PRELOAD before the YAMD shared object was

  added.

 

You will probably also want to symify the logfile to translate the

addresses into file and line numbers.  The `do-syms' program

accomplishes this.  It takes the executable as its only argument,

reads the logfile from stdin, and writes the symified version to

stdout.

 

 

Interpreting the logfile

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

 

To be written.  Hopefully the logfile is fairly self-explanatory.

 

 

Debugging

---------

 

If your program does something erroneous, it may crash, giving you a

core dump or traceback.  (On Linux, you will also get a traceback and

details about the faulty operation in the logfile.)  You can then use

usual postmortem debugging techniques to find the bug.

 

You can also run your YAMD'd program under a debugger.  Be sure to set

the environment variables appropriately.  In my experience, statically

YAMD'd programs work better under a debugger.  The function

`__yamd_describe_address' is intended for use within debuggers and,

when called with an address as its single arg, will print a

description of the block, if any, in or near which the address lies.

 

For DJGPP, see also "Caveats".

 

 

Caveats

-------

 

General:

 

You may catch libc operations.  As of v0.30, the only effect of this

should be cluttering of your logfile, and perhaps bogus memory leaks.

(This seems to be particularly true with DJGPP.)  Use the tracebacks

to decide whether it really is your bug.

 

Some assumptions are made about the workings of the libc mallocs.  If

you are using your own malloc and family, you're on your own.

 

You really do need a lot of virtual memory for a project of any size!

 

DJGPP:

 

The current DJGPP debuggers don't check page protection, and so they

will crash if they try to access a page that YAMD has protected.  A

patch is included as `dbgcom.dif'; it's against the latest development

DJGPP version.  You will need to recompile libdbg and the appropriate

debuggers.  Patched debuggers are available at

 

GDB has an additional bug whereby it ignores info on whether an

address is accessible; a patch is included as `gdb.dif'.

 

DJGPP v2.01 has a bug that makes test10 fail with an infinite

traceback; if you see this, upgrade to 2.02 or the latest version.

 

If you have troubles with running out of memory when you think you

shouldn't, see if FAQ chapter 15 helps.

 

I repeat: You must run under plain DOS with CWSDPMI!

 

 

Linux:

 

glibc 2.1 or above is highly recommended.  It provides the

`backtrace_symbols' function which will allow your tracebacks to show

functions inside shared libraries (like libc).  Your shared libraries

must be unstripped for this to work.

 

If you have only glibc 2.0 or less, shared library symbols will not be

reliable.  You can get libc symbols by linking with `-static'.

Otherwise, you should be suspicious of any entry with an address in

the mmap area (around 0x40000000).

 

If you have only libc5, the above still applies.  Furthermore,

dynamically loaded YAMD does not work at all with libc5.  I suggest

you upgrade soon, for many more reasons than just this package.

 

A 2.2 or late 2.1 kernel will give you the full path to the executable

in the logfile.  Otherwise, you'll see only its device and inode.

 

GDB does not seem to interact well with shared libraries, particularly

in core dumps.  Perhaps this is because YAMD is not linked to the

program, but merely preloaded.  Statically linked YAMD is more

successful.

 

I have not tested the run-yamd shell script with any shell except

bash.  If it needs changes, please let me know.

 

Bugs

----

 

None known and confirmed, but they surely exist.

 

 

Credits

-------

 

Some concepts were inspired by the following pieces of software:

 

* MSS by Juan Jesus Alcolea Picazo and Peter Palotas

 

* ElectricFence by Bruce Perens

 

* The GNU C library, by quite a lot of people.

 

However, all code is original.

 

 

Thanks also to Salvador Eduardo Tropea, Alex Lozano, Eli Zaretskii,

Martijn Versteegh, Michael Reggio, Waldemar Schultz, and probably

several people I have forgotten, for their comments, suggestions, and

bug reports.

 

 

Contact

-------

 

Please send suggestions, bug reports, etc. to me, Nate Eldredge, at

.

 

This file and the rest of YAMD is copyright (C) 1999 by Nate Eldredge.

There is no warranty whatever; I disclaim responsibility for any

damage caused.  Released under the GNU General Public License (see the

file COPYING).

 

阅读(1142) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~