//---------------------------------------------------------------- // scanning.s // // This is an extension of our earlier 'showproc.s' program // which read the contents of the '/proc/self/maps' pseudo- // file into a memory buffer. Here we use the Intel string // instructions 'scasb' and 'cmpsb' to scan for information // which describes the address-range of the stack's memory. // // assemble using: $ as scanning.s -o scanning.o // and link using: $ ld scanning.o -o scanning // // programmer: ALLAN CRUSE // written on: 13 FEB 2006 // revised on: 15 FEB 2006 -- to scan for stack-segment info //---------------------------------------------------------------- # manifest constants .equ sys_exit, 1 .equ sys_read, 3 .equ sys_write, 4 .equ sys_open, 5 .equ O_RDONLY, 0 .equ STDOUT, 1 .equ BUFSIZE, 4096 .section .data filename: .asciz "/proc/self/maps" # pseudo-file's name legend: .ascii "[stack]" # label on stack-region info .section .bss filesiz: .space 4 # holds the pseudo-file size file_id: .space 4 # holds the pseudo-file's ID buf: .space BUFSIZE # holds the pseudo-file data len: .space 4 # holds current line's length ptr: .space 4 # holds pointer to stack-line .section .text _start: # open the pseudo-file for reading mov $sys_open, %eax # setup service ID-number lea filename, %ebx # setup pointer to filename mov $O_RDONLY, %ecx # specify file's access-mode int $0x80 # invoke the kernel service mov %eax, file_id # save pseudo-file's handle # read from the pseudo-file mov $sys_read, %eax # setup service ID-number mov file_id, %ebx # setup the file's handle lea buf, %ecx # setup the buffer address mov $BUFSIZE, %edx # and maximum bytes to read int $0x80 # invoke the kernel service mov %eax, filesiz # save count of bytes read # now we enter a loop which examines each line in the buffer # in order to determine (1) its length, and then (2) whether # or not that line describes this task's stack-segment. The # start-address of the line describing the stack is saved as # 'ptr' so we can then write it to the display-device. Note # that each line in the pseudo-file includes a 'legend' that # begins in column number 49 and describes a memory-segment. xorl %ebx, %ebx # setup initial buffer index cld # perform forward processing nxline: leal buf(%ebx), %esi # point ESI to current line # scan the current line for its end-of-line ascii-code movl %esi, %edi # copy line-pointer to EDI movl filesiz, %ecx # total size of buffer data subl %ebx, %ecx # minus data in prior lines movb $'\n', %al # setup target-byte in AL repne scasb # scan for end-of-line mark subl %esi, %edi # length is finish - start movl %edi, len # save this line's length # check the current line for the "[stack]" legend leal 49(%esi), %edi # address of legend-field leal legend, %esi # & legend-pointer in ESI movl $7, %ecx # legend-length into ECX repe cmpsb # compare the two strings je found # strings agree? save EBX # advance line-offset in EBX to the following line addl len, %ebx # add line-length to EBX cmpl filesiz, %ebx # check: EBX < filesize? jb nxline # yes, more lines to scan jmp quit # else scanning is done found: # save a pointer to the current line describing the stack leal buf(%ebx), %esi # get this line's address movl %esi, ptr # and save for use below # now show the line that describes the stack-segment movl $sys_write, %eax # setup service ID-number movl $STDOUT, %ebx # setup device ID-number movl ptr, %ecx # point to relevant line movl len, %edx # and setup line's length int $0x80 # invoke kernel service quit: # terminate this program mov $sys_exit, %eax # setup service ID-number xor %ebx, %ebx # return 0 as exit-code int $0x80 # invoke kernel service .global _start .end