GDB进阶之路_new_第1页
GDB进阶之路_new_第2页
GDB进阶之路_new_第3页
GDB进阶之路_new_第4页
GDB进阶之路_new_第5页
已阅读5页,还剩26页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、GDB进阶之路Consumer公共部件开发部潘剑目录n基础篇n进阶篇n高级篇基础篇:GDB之必备基础篇:GDB之必备nUNIX下用到的一些库类型类型使用方式使用方式优点优点缺点缺点静态链接库(*.a)在程序链接时,把第三方的库文件链接进可执行文件。不依赖于具体执行环境。编译速度慢,可执行文件占用空间大,运行时耗内存。动态链接库(*.so)程序链接时,只把依赖的动态链接库的库名放入可执行文件中。编译速度快,编译后的执行文件占用空间小,省内存。依赖于具体执行环境是否有程序使用的第三方库。基础篇:GDB之必备nGDB 常用命令命令命令描述描述list (l)列出产生执行文件的源代码的一部分 run

2、(r)执行当前被调试的程序 continue (c)从断点挂起处继续执行next (n)执行一行源代码但不进入函数内部 step (s)执行一行源代码而且进入函数内部 print (p)打印变量值 quit (q)终止 gdb watch (w)使你能监视一个变量的值而不管它何时被改变 break (b)在代码里设置断点, 这将使程序执行到这里时被挂起。基础篇:GDB调试举例#gcc -g a.c -o a.out 编译时编译时-g 打开调试选项;打开调试选项;#gdb a.out 注意注意gdb后面跟的是可执行程序;后面跟的是可执行程序;GNU gdb 6.6Copyright (C) 20

3、06 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type show copying to see the conditions.There is absolutely no warranty for GDB. Type show warranty for details.Th

4、is GDB was configured as x86_64-suse-linux.(gdb)l l是是list的缩写,是查看源程序内容的命令;的缩写,是查看源程序内容的命令;1 #include2 #include3 int main(int argc,char* argv)4 5 unsigned short s;(gdb) 直接回车时重复执行上次的命令;直接回车时重复执行上次的命令;基础篇:GDB调试举例(gdb)b 15 “b+数字数字”是在某一行设置一个断点,可以同时设置多个断点;是在某一行设置一个断点,可以同时设置多个断点;Breakpoint 1 at 0 x80483c4:

5、file overflow.c, line 15. (gdb)r 5 hello 运行程序,在设置的断点处停止。注意程序的运行规则,如加参数等;运行程序,在设置的断点处停止。注意程序的运行规则,如加参数等;Starting program: /root/test/day7/a.out 5 helloBreakpoint 1, main (argc=3, argv=0 xbfffdea4) at overflow.c:15 停止在断点处;停止在断点处;15 i=atoi(argv1);(gdb)p i 查看一下此时变量查看一下此时变量i的值;的值; $1 = -1073747112 由于由于i此

6、时还未有值,出现一个随机的值;此时还未有值,出现一个随机的值;(gdb)n 单步执行程序后半部分;单步执行程序后半部分;16s=i; 显示执行的是哪一行;显示执行的是哪一行;(gdb)p i 查看执行上一步语句之后变量查看执行上一步语句之后变量i的值;的值; $2 = 5(gdb)info break 查看整个程序断点信息,如断点的个数及其位置;查看整个程序断点信息,如断点的个数及其位置;Num Type Disp Enb Address What1 breakpoint keep y 0 x080483c4 in main at overflow.c:15 breakpoint alread

7、y hit 1 time(gdb)info all 显示整个程序运行到此时,各个寄存器中的值;显示整个程序运行到此时,各个寄存器中的值;进阶篇:简单又不简单的命令1、continue/step/next分别简称c/s/n,很常用的命令,另外,还有一个 start命令,很方便的命令,其相当于在程序首行设定一个断点首行设定一个断点然后运行run。2、break简称b,此外,我们一般都先入为地把break N当成break的基本格式,其实break是可以跟条件表达式条件表达式,比如 break cm_xxx.C:158 if x 0 xffff0000,这个功能有的时候比watch好用多了。3、pr

8、int调试程序过程中,可以用print来修改变量值修改变量值,格式如下:(gdb) print x=44、print用print打印打印STL容器容器的方法:void dump(std:map& x) for(std:map:const_iterator i = x.begin(), j(x.end(); i != j; i+) printf(“x%d = %d”, i-first, i-second);进阶篇:简单又不简单的命令int main() std:map x; x2 = 20; x4 = 40;(gdb) l 11 12 std:map x;13 x2 = 20;14 x4

9、 = 40;(gdb) b 14Breakpoint 1 at 0 x71429cc: file test.cc, line 14.(gdb) reading symbols from shared object read from target memory.done.Breakpoint 1, main () at tmp.c:1414 x4 = 40;(gdb) n15 (gdb) call dump(x)x2 = 20 x4 = 40进阶篇:简单又不简单的命令4、print依旧调试程序过程中,可以用print来修改变量值修改变量值,格式如下:(gdb) print x=45、jump指

10、定下一条语句的运行点,可以访问程序的任意一处语句任意一处语句,格式参考break命令,可以是filename:linenum格式,可以是+xxx这种偏移量格式。但是,jump命令不会改变当前栈中的内容,所以,当从一个函数跳到另一个函数时,肯定会发生错误,甚至于产生程序的coredump,所以该命令只适用于同一函数下的任意跳转。进阶篇:变量查看的技巧1、 在GDB中,你可以随时查看以下三种变量的值: 全局变量(所有文件可见的) 静态全局变量(当前文件可见的) 局部变量(当前Scope可见的)另外,变量冲突的情况下可以用域操作符“:”,可以文件指定或类、函数指定,例如:file:variablef

11、unction:variable2、 固定长度打印数组信息(gdb) p *array3$1 = 0, 1, 2(gdb) p *array10$2 = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9(gdb)进阶篇:变量查看的技巧3、 打印unicode字符串信息,例如:(gdb) startBreakpoint 1 at 0 x40055c: file a.C, line 6.Starting program: /home/zyy/a.outmain () at a.C:66 char * szAnsi = Innovating Together Across Borders;(

12、gdb) n7 wchar_t * szUnicode =L软通动力 创新无边界;(gdb)8 (gdb) p szAnsi$1 = 0 x400670 Innovating Together Across Borders(gdb) p szUnicode$2 = (wchar_t *) 0 x400698直接调用print命令无法打印汉字,只会列出首地址,所以我们要想个办法,类似于前面的call功能,不过是利用gdb本身提供的接口和语法。进阶篇:变量查看的技巧A.修改.gdbinit文件,该文件是gdb启动时读的一个配置项,提供了接口定义,我们可以定义一个wprint接口,负责打印双字节。d

13、efine wprintset $fd = open(/tmp/wprint, 577)set $x = write($fd, $arg0, wcslen($arg0) * sizeof(wchar_t)set $y = close($fd)shell wprintendB.提供wprint命令的实现,并生成wprint可执行文件,如下:setlocale(LC_ALL, ); const char* file_name = /tmp/wprint; FILE* f = fopen(file_name, rb); if(f = 0) printf(Open %s error! , file_n

14、ame); return -1; fseek(f, 0, SEEK_END); long file_size = ftell(f) + 1; fseek(f, 0, SEEK_SET); wchar_t* buf = (wchar_t*)malloc(file_size + sizeof(wchar_t); int r = fread(buf, 1, file_size, f); buffile_size / sizeof(wchar_t) = 0; printf(%S , buf); free(buf);进阶篇:变量查看的技巧C.将wprint文件拷到/tmp和/usr/bin中,此时便相当

15、于添加了一个wprint命令。(gdb) startBreakpoint 1 at 0 x40055c: file a.C, line 6.Starting program: /home/zyy/a.outmain () at a.C:66 char * szAnsi = Innovating Together Across Borders;(gdb) n7 wchar_t * szUnicode =L软通动力 创新无边界;(gdb)8 (gdb) p szAnsi$1 = 0 x400670 Innovating Together Across Borders(gdb) p szUnicod

16、e$2 = (wchar_t *) 0 x400698(gdb) wprint szUnicode软通动力 创新无边界 (gdb)进阶篇:变量查看的技巧4、 查看内存使用examine命令(简写是x)来查看内存地址中的值,语法如下(n、f、u时可选参数):x/n:表示显示内存的长度。f:表示显示的格式。u:表示从当前地址往后请求的字节数。n/f/u三个参数可以一起使用。例如:命令:x/3uh 0 x54320 表示,从内存地址0 x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。其实用的最多的也最简单的,就是直接后面带上数字,每次显示一个4字节的信息,从低字

17、节开始数,例如:main () at a.C:66 char * tmp = 1234567890;(gdb) p tmp$1 = 0 x400670 1234567890(gdb) x /4 0 x4006700 x400670: 0 x34333231 0 x38373635 0 x00003039 0 x00000000(gdb) 进阶篇:变量查看的技巧5、 查看结构体(类)A.改变结构体显示方式,便于查看:(gdb) p a$1 = a = 1, b = 2, c = 0 x400690 1234567890(gdb) set print pretty on(gdb) p a$2 =

18、a = 1, b = 2, c = 0 x400690 1234567890(gdb) B.当显示结构体含结构体时,变量显示时会出现省略号,打开开关即可显示内部信息:set print union当打开这个开关时,执行 p foo 命令后,会如下显示:$1 = it = Tree, form = tree = Acorn, bug = Cocoon当关闭这个开关时,执行 p foo 命令后,会如下显示:$1 = it = Tree, form = .进阶篇:多线程状态查看1、线程产生通知:在产生新的线程时, gdb会给出提示信息(gdb) r 运行程序;运行程序;Starting progra

19、m: /home/zyy/bin/taskmanagerwarning: Lowest section in system-supplied DSO at 0 xffffe000 is .hash at ffffe0b4Thread debugging using libthread_db enabledNew Thread 4156778160 (LWP 4695)infoX-MDSP taskmanager R003C03L10205 for Linux built on 2010-06-29 20:39:18Copyright(c) 2001-2006, Huawei Technolog

20、ies Co., Ltd. All rights reserved.Now taskmanager is starting -以下三个为新产生的线程,共四个线程。以下三个为新产生的线程,共四个线程。New Thread 4126702496 (LWP 4851)New Thread 4118309792 (LWP 4852)New Thread 4109917088 (LWP 4853)Now taskmanager is ready 进阶篇:多线程状态查看2、查看线程:使用info threads可以查看运行的线程。 (gdb) info thread 查看线程信息;查看线程信息; 4 Th

21、read 4109917088 (LWP 4853) 0 xffffe410 in _kernel_vsyscall () 3 Thread 4118309792 (LWP 4852) 0 xffffe410 in _kernel_vsyscall () 2 Thread 4126702496 (LWP 4851) 0 xffffe410 in _kernel_vsyscall ()* 1 Thread 4156778160 (LWP 4695) 0 xffffe410 in _kernel_vsyscall ()(gdb)如上,前面有“*”号的就是当前线程,同时可以使用thread xxx进

22、行进程切换:(gdb) thread 2 切换线程;切换线程;Switching to thread 2 (Thread 4126702496 (LWP 4851)#0 0 xffffe410 in _kernel_vsyscall ()(gdb) info thread 查看线程信息;查看线程信息; 4 Thread 4109917088 (LWP 4853) 0 xffffe410 in _kernel_vsyscall () 3 Thread 4118309792 (LWP 4852) 0 xffffe410 in _kernel_vsyscall ()* 2 Thread 412670

23、2496 (LWP 4851) 0 xffffe410 in _kernel_vsyscall () 1 Thread 4156778160 (LWP 4695) 0 xffffe410 in _kernel_vsyscall ()(gdb)进阶篇:多线程状态查看3、多线程中加断点(其实和单线程一样,只要记牢各个线程的id就可以轻松切换各个断点)(gdb) b TNotifyUserTask:process() 直接对代码上进行断点,无须强调线程;直接对代码上进行断点,无须强调线程;Breakpoint 1 at 0 x805393c: file /home/zyy/source/taskmg

24、r/tm_notifyusertask.C, line 180.(gdb) r 运行程序;运行程序;Starting program: /home/zyy/bin/taskmanagerwarning: Lowest section in system-supplied DSO at 0 xffffe000 is .hash at ffffe0b4Thread debugging using libthread_db enabledNew Thread 4156942000 (LWP 28532) 主线程;主线程;infoX-MDSP taskmanager R003C03L10205 for

25、 Linux built on 2010-06-29 20:39:18Copyright(c) 2001-2006, Huawei Technologies Co., Ltd. All rights reserved.Now taskmanager is startingNew Thread 4126866336 (LWP 28673) 顺序起了多个子线程;顺序起了多个子线程;New Thread 4118473632 (LWP 28675)New Thread 4110080928 (LWP 28676)Now taskmanager is readySwitching to Thread

26、4126866336 (LWP 28673)Breakpoint 1, TNotifyUserTask:process (this=0 x8753908) at 时间片切换到该线程,断点;时间片切换到该线程,断点; /home/zyy/source/taskmgr/tm_notifyusertask.C:180180 RUNLOG(TLogLevel_Debug, TLogID_PrintInfo, TNotifyUserTask:process);进阶篇:多线程状态查看4、指定线程执行gdb命令 (gdb) info thread 现在运行在现在运行在2号线程;号线程; 4 Thread 4

27、110080928 (LWP 28676) 0 xffffe410 in _kernel_vsyscall () 3 Thread 4118473632 (LWP 28675) 0 xffffe410 in _kernel_vsyscall ()* 2 Thread 4126866336 (LWP 28673) TNotifyUserTask:process (this=0 x8753908) at /home/zyy/source/taskmgr/tm_notifyusertask.C:180 1 Thread 4156942000 (LWP 28532) 0 xffffe410 in _k

28、ernel_vsyscall ()(gdb) thread apply 1 b TNotifySPTask:isBuffHandleOver() 当切换到当切换到1号线程(号线程( 28532 )时,再次设置断点)时,再次设置断点2在在TNotifySPTask:isBuffHandleOver() Thread 1 (Thread 4156942000 (LWP 28532):Breakpoint 2 at 0 x80552d7: file /home/zyy/source/taskmgr/tm_notifysptask.C, line 595.180 RUNLOG(TLogLevel_De

29、bug, TLogID_PrintInfo, TNotifyUserTask:process);(gdb) cContinuing.Switching to Thread 4118473632 (LWP 28675)Breakpoint 2, TNotifySPTask:isBuffHandleOver (this=0 x875384c) at 断点断点2 /home/zyy/source/taskmgr/tm_notifysptask.C:595595 return (m_iLastProcessPos = m_iBuffSize);进阶篇:多线程状态查看5、多线程调试要记住,多用tbrea

30、k来断点程序,善用watch来跟踪变量。6、多线程的coredump,多为段错误,一般都涉及内存非法读写,对于core文件的检视,上述线程操作也是适用的。如果都看不出来,就仔细查看代码,看看是不是在if,return,break,continue这种语句操作是忘记解锁忘记解锁,还有嵌套锁嵌套锁的问题,都需要分析清楚了。最后说一句,碰到多线程的coredump,捶胸顿足是没有用的,静下心来看代码才是王道!高级篇:strip命令的使用 GNU附带的瘦身工具命令strip,是跟随gcc、g+一起发布的C/C+开发套件中的一个工具(适用于目前的suse,AIX环境),能清除执行文件中不必要的标示符及调

31、试信息(-g编译选项引入),可显著减小文件大小而不影响正常使用。当然,由于strip后的文件不包含调试信息,就不能直接用于调试和core问题定位,但是可以用strip前的文件打开core文件。一旦现网发生coredump,将core文件取回来之后,再用对应的原始文件就可以查看详细的core信息,实例如下:strip a.out 对可执行文件对可执行文件strip;ls -al a.*-rw-r- 1 zyy users 511 2010-07-31 10:27 a.C-rwxr-x- 1 zyy users 4984 2010-07-31 11:38 a.out*-rwxr-x- 1 zyy

32、users 10761 2010-07-31 10:27 a.out.bak* 原始文件的备份;原始文件的备份;高级篇:strip命令的使用使用使用strip后的后的a.out查看查看core信息:信息:gdb a.out coreCore was generated by a.out.Program terminated with signal 11, Segmentation fault.#0 0 x00000000004005a5 in _gxx_personality_v0 ()使用使用strip前的原始文件查看前的原始文件查看core信息:信息:gdb a.out.bak coreC

33、ore was generated by a.out.Program terminated with signal 11, Segmentation fault.#0 0 x00000000004005a5 in main () at a.C:3737strcpy(aaa, 0123456789000);PS:貌似文件越大,:貌似文件越大,strip后的体积缩小比例就越大。后的体积缩小比例就越大。-rwxrwxrwx 1zyy users 4842772 2010-07-31 11:27 latebilling*-rwxr-x- 1zyy users 15717616 2010-07-31 1

34、1:27 latebilling_bak*高级篇:栈破坏core问题定位如下是正常的堆栈信息,一般人都能从堆栈中获取到足够的信息进行问题定位,每层堆栈中保存着一个4个字节的信息,这些就是函数入口地址或参数地址。只要编译代码时加上-g选项,那么呈现在堆栈中的这些地址便会映射为具体的函数名称:#0 0 x083de6c1 in CNlIPPkgHandler:OnIPMessage (this=0 x57206cfc, pRawData=0 x57fe7008 005) at /home1/da1xcom/WISGdA12/src/parser/common/netlink/NetlinkHand

35、ler.cpp:705705 int iThread = CServiceThread:Dispatch(pParam-m_uiUserIP);(gdb) bt#0 0 x083de6c1 in CNlIPPkgHandler:OnIPMessage (this=0 x57206cfc, pRawData=0 x57fe7008 005) at /home1/da1xcom/WISGdA12/src/parser/common/netlink/NetlinkHandler.cpp:705#1 0 x083dd008 in CNetlinkHandler:handle_input (this=0

36、 x57206cfc) at /home1/da1xcom/WISGdA12/src/parser/common/netlink/NetlinkHandler.cpp:120#2 0 x083e0a0b in CNLIPPkgRecvThread:Run (this=0 x57206be0) at /home1/da1xcom/WISGdA12/src/parser/common/netlink/NetlinkThread.cpp:268#3 0 x080c5fac in CThread:svc (this=0 x57206be0) at /home1/da1xcom/WISGdA12/src

37、/common/thread/Thread.cpp:228#4 0 x08418910 in ACE_Task_Base:svc_run (args=0 x57206be0) at Task.cpp:258#5 0 x0842b7c8 in ACE_Thread_Adapter:invoke (this=0 x57206fb0) at Thread_Adapter.cpp:95#6 0 x555992ab in start_thread () from /lib/libpthread.so.0#7 0 x55771a4e in clone () from /lib/libc.so.6(gdb)

38、 高级篇:系统中的寄存器(gdb) info registerseax 0 x875384c 141899852ecx 0 x0 0edx 0 x8057e92 134577810ebx 0 x144db2e 21289774esp 0 xf57ae3c8 0 xf57ae3c8ebp 0 xf57ae3c8 0 xf57ae3c8esi 0 xf57aeba0 -176493664edi 0 x0 0eip 0 x80552d7 0 x80552d7 eflags 0 x282 SF IF cs 0 x23 35ss 0 x2b 43ds 0 x2b 43es 0 x2b 43fs 0 x0

39、 0gs 0 x63 99高级篇:堆栈的示例堆栈是一种简单的数据结构,是一种只允许在其一端进行插入或删除的线性表,允许插入或删除操作的一端称为栈顶,另一端称为栈底,对应的指令分别为,POP指令实现出栈操作,PUSH指令实现入栈操作。其中,ESP寄存器存放当前线程的栈顶指针,EBP寄存器中保存当前线程的栈底指针。示例如下:pushebp ebp入栈 mov ebp,esp esp是堆栈指针,无法暂借使用,所以得用ebp来存取堆栈 sub esp,4*5 下面的sprintf一共使用了5个参数push1111 push2222 push3333 pushoffsetszFormat pushoff

40、setszOut callsprintf调用wsprintf addesp,4*5 堆栈使用完毕,“还”回4*5个字节给系统 . movesp,ebp 恢复esp的值 popebp ebp出栈 ret 高级篇:获取函数和参数指针1 1、获取栈顶开始数的124个四字节数据,每个数字表示一个函数指针、参数指针或函数内部的局部变量。(gdb(gdb) x /124w ) x /124w $esp$esp0 xf6c5b020: 0 x00100010 0 x00000000 0 xef2ff000 0 xef2ff0000 xf6c5b020: 0 x00100010 0 x00000000 0 x

41、ef2ff000 0 xef2ff0000 xf6c5b030: 0 x00000118 0 x00000008 0 xf6c5b068 0 x0819d8d90 xf6c5b030: 0 x00000118 0 x00000008 0 xf6c5b068 0 x0819d8d90 xf6c5b040: 0 xef2ff000 0 x084d5061 0 x00000008 0 x081a25a70 xf6c5b040: 0 xef2ff000 0 x084d5061 0 x00000008 0 x081a25a70 xf6c5b050: 0 xf7e8aff4 0 xf2100010 0 x

42、000001b4 0 xef2feee80 xf6c5b050: 0 xf7e8aff4 0 xf2100010 0 x000001b4 0 xef2feee80 xf6c5b060: 0 xe7743c48 0 x000001bc 0 xf6c5b098 0 x0819f0ca0 xf6c5b060: 0 xe7743c48 0 x000001bc 0 xf6c5b098 0 x0819f0ca0 xf6c5b070: 0 xf7ab3398 0 xef2feee8 0 x084d5061 0 x000001bc0 xf6c5b070: 0 xf7ab3398 0 xef2feee8 0 x

43、084d5061 0 x000001bc0 xf6c5b080: 0 xef9f5878 0 xf7f90ff4 0 xf6c5b098 0 xe7743c480 xf6c5b080: 0 xef9f5878 0 xf7f90ff4 0 xf6c5b098 0 xe7743c480 xf6c5b090: 0 xed65e0b0 0 xf7ab3398 0 xf6c5b0c8 0 x081a28180 xf6c5b090: 0 xed65e0b0 0 xf7ab3398 0 xf6c5b0c8 0 x081a28180 xf6c5b0a0: 0 xf7ab3398 0 xe7743c48 0 x

44、ef2feee8 0 x000001bc0 xf6c5b0a0: 0 xf7ab3398 0 xe7743c48 0 xef2feee8 0 x000001bc0 xf6c5b0b0: 0 x000000010 xf6c5b0b0: 0 x00000001 0 x00000001 0 x000000010 x00000001 0 x00000001 0 x000001bc 0 x000001bc0 xf6c5b0c0: 0 xef2feee8 0 x00000002 0 xf6c5b0f8 0 x081a2a870 xf6c5b0c0: 0 xef2feee8 0 x00000002 0 xf

45、6c5b0f8 0 x081a2a87高级篇:反编译入口地址2、紧接着便是从栈顶对每个地址进行反编译,如下:(gdb) disassemble 0 x00100010No function contains specified address.(gdb) disassemble 0 x00000000No function contains specified address.(gdb) disassemble 0 xef2ff000No function contains specified address. .(gdb) disassemble 0 x0819D8D9Dump of ass

46、embler code for function _ZN18CHttpHandlerObject6memstrEPcS0_j:0 x0819d890 :push %ebp0 x0819d891 :mov %esp,%ebp. .End of assembler dump.(gdb) disassemble 0 xf6c5b098No function contains specified address.(gdb) disassemble 0 x0819f0caDump of assembler code for function _ZN18CHttpHandlerObject21ParseTransferEncodingEP16CTransactionItemPcj9EMOMTFlag:0 x0819f080 :push %ebp. .End of assembler dump. .高级篇:反编译示例3、然后把每个地址的反编译结果按栈顶到栈底的顺序排列,则函数调用顺序便出来了,同时可以根据函数具体调用信息对于函数调用进行进一步的判断。 0 xef2feee8 / p (char *)0 xef2feee8 0 xe7743c48 / p *(CTransactio

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论