I'll admit to being completely new to Windbg so hopefully this is a noobish question that I couldn't find the answer for on the internet.
Anyways, here is my symbol path: SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
I have a small command line program that I made, so I go to File -> Open Executable
I select the .exe and give it the two arguments from that screen. I then go to the Command window and press 'g' to run my program. I get the following output.
CommandLine: C:\Users\me\devcode\folder\program\myprogram.exe input1 outputdir
Symbol search path is: SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 01320000 01367000 image01320000
ModLoad: 779b0000 77b30000 ntdll.dll
ModLoad: 76e30000 76f40000 C:\Windows\syswow64\kernel32.dll
ModLoad: 76790000 767d7000 C:\Windows\syswow64\KERNELBASE.dll
(19a8.1cf0): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=cb5b0000 edx=0026ddf8 esi=fffffffe edi=00000000
eip=77a50fab esp=001af830 ebp=001af85c iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2c:
77a50fab cc int 3
0:000> g
(19a8.1cf0): Stack overflow - code c00000fd (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
*** ERROR: Module load completed but symbols could not be loaded for image01320000
eax=008872a8 ebx=7efde000 ecx=008872a8 edx=00887e60 esi=00000000 edi=00000000
eip=01327076 esp=000b2fe4 ebp=000b3028 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
image01320000+0x7076:
01327076 53 push ebx
I am most concerned about the line that reads:
*** ERROR: Module load completed but symbols could not be loaded for image01320000
Where does image01320000 come from? Shouldn't this be the name of my executable? I do have .pdb files that were created.
Yes, my program is built in debug mode. I'm just trying to get a stacktrace so I can find the source of the stack overflow it is reporting.
Thank you!
Related
NOTE: While I mainly focus on using GDB as a debugger in this question, I've noticed the same behavior in other debugging tools (Forge DDT does the same thing as well)
I'm trying to troubleshoot some really old Fortran code with GDB. It isn't actually crashing, just printing a non-descriptive "Error Encountered" message on stdout.
I've isolated the subroutine that prints the non-helpful error message, and am trying to use GDB backtrace to figure out what's actually happening when it stops. Except, the backtrace keeps point back to a nonsensical section of code when it fires. It may look something like this in my progmain.F file:
...
246 inum=number
247 number=number-1
248 call func
249 call error(999,0,0,0,zero,'func')
...
then I have another source file helper.F with:
722 subroutine error(num,i1,i2,i3,r,c)
This will correspond to a gdb output of:
(gdb) break error
(gdb) run
Breakpoint 1, error (num=999, i1=0, i2=0, i3=0, r=0, c=..., .tmp.C.len_V$757=6)
at helper.F:722
722 subroutine error (num,i1,i2,i3,r,c)
Missing separate debuginfos, use: zypper install libgcc_s1-debuginfo-10.3.0+git1587-1.6.4.x86_64
(gdb) bt
#0 error (num=999, i1=0, i2=0, i3=0, r=0, c=..., .tmp.C.len_V$757=6)
at helper.F:722
#1 0x00000000004036a2 in progmain () at progmain.F:246
...
Note that line 246 in progmain.F is not a call to error, it's an assignment operator 3 lines above what I presume is the call to error that triggered the breakpoint.
The issue is, sometimes it isn't obvious which call to error is triggering the breakpoint. In particular, one breakpoint trigger has a backtrace that leads to the middle of a bunch of commented lines in progmain.F which are in between calls to error--and the code itself is RIFE with go to jumps so I can't actually tell what call to error is actually triggering the breakpoint.
Why are the line numbers inaccurate? How can I make bt actually point back to the line where error was called? I'm compiling with -O0 and -g so it shouldn't be an optimizer issue...
UPDATE: Following a comment in response to this thread, I tried doing a frame 1 command followed by disas /m in gdb. I then paged through the assembly code until I reached the section of code in question The disas output looks like:
245 x=0
0x00000000004036d7 <+359>: mov $0x0,%eax
0x00000000004036dc <+364>: call 0x5d0dbf <func>
246 inum=number
0x00000000004036e1 <+369>: add $0xfffffffffffffff0,%rsp
0x00000000004036e5 <+373>: mov $0x75a988,%eax
0x00000000004036ea <+378>: mov $0x75a984,%edx
0x00000000004036ef <+383>: mov $0x75a984,%ecx
0x00000000004036f4 <+388>: mov $0x75a984,%ebx
0x00000000004036f9 <+393>: mov $0x11096c0,%esi
0x00000000004036fe <+398>: mov $0x75a3e0,%edi
0x0000000000403703 <+403>: movq $0x6,(%rsp)
0x000000000040370b <+411>: mov %rdi,-0x5a8(%rbp)
0x0000000000403712 <+418>: mov %rax,%rdi
0x0000000000403715 <+421>: mov %rsi,-0x5a0(%rbp)
0x000000000040371c <+428>: mov %rdx,%rsi
0x000000000040371f <+431>: mov %rcx,%rdx
0x0000000000403722 <+434>: mov %rbx,%rcx
0x0000000000403725 <+437>: mov -0x5a0(%rbp),%rax
0x000000000040372c <+444>: mov %rax,%r8
0x000000000040372f <+447>: mov -0x5a8(%rbp),%rax
0x0000000000403736 <+454>: mov %rax,%r9
0x0000000000403739 <+457>: mov $0x0,%eax
0x000000000040373e <+462>: call 0x644c45 <error>
=> 0x0000000000403743 <+467>: add $0x10,%rsp
247 number=number-1
248 call func
249 call error(999,0,0,0,zero,'func')
So if I'm reading this right, the assembly isn't happening in the same order as the original code. The call to func is happening first, then number is being loaded and decremented, then error is being called, and I guess this re-arrangement is breaking the debugging symbols? Why is this happening when I'm compiling without optimizations?
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a Visual Studio C/C++ project with a single assembly file main.asm in it. During the process of building the project I get the errors:
1>main.asm(5): error A2008: syntax error : .
1>main.asm(6): error A2008: syntax error : .
1>main.asm(7): error A2008: syntax error : .
1>main.asm(8): error A2008: syntax error : ,
1>main.asm(20): error A2008: syntax error : INVOKE
My code for main.asm is:
; program 3.1
; sample Assembly program - MASM (32-bit)
.386 ; Line 5
.MODEL FLAT, stdcall ; Line 6
.STACK 4096 ; Line 7
ExitProcess PROTO, dwExitCode:DWORD ; Line 8
.data
sum DWORD 0
.code
_main PROC
mov eax, 25
mov ebx, 50
add ebx, ebx
mov sum, eax
INVOKE ExitProcess, 0 ; Line 20
_main ENDP
END
A screenshot of Visual Studio with my code and the errors:
Why am I getting these errors and how can I fix them?
Based on the errors you are showing on the line starting with .MODEL, .STACK, and .386 I can only gather that you are building for a 64-bit target rather than a 32-bit target. You likely also received errors related to the INVOKE directive as well. None of these directives are supported by 64-bit MASM and thus are generating errors. In 64-bit code the model is always assumed to be flat and the calling conventions for CDECL, STDCALL, THISCALL, FASTCALL etc are all the same and follow the Windows 64-bit Calling Convention.
You have two choices:
Build a 32-bit application. In Visual Studio as part of the menu bars there is a pull down box for the platform. The platform can be adjusted in the toolbar by changing x64 to x86:
Modify the code to work with 64-bit code. To build in 64-bit you have to replace INVOKE with CALL and the Windows 64-bit calling convention must be used. You can remove the .STACK, .MODEL, and .386 directives. Modify the definition of the external procedures by declaring them EXTERN with a PROC type. The code could look something like:
; program 3.1
; sample Assembly program - MASM (64-bit)
extern ExitProcess:PROC
public mainCRTStartup
.data
sum DWORD 0
.code
mainCRTStartup PROC ; Use mainCRTStartup if making a CONSOLE app without
; any C/C++ files AND if you haven't overridden the
; ENTRY point in the Visual Studio Project.
sub rsp, 8+32 ; Align stack on 16 byte boundary and allocate 32 bytes
; of shadow space for call to ExitProcess. Shadow space
; is required for 64-bit Windows Calling Convention as
; is ensuring the stack is aligned on a 16 byte boundary
; at the point of making a call to a C library function
; or doing a WinAPI call.
mov eax, 25
mov ebx, 50
add ebx, ebx
mov sum, eax
xor ecx, ecx ; Set Error Code to 0 (RCX is 1st parameter)
call ExitProcess
mainCRTStartup ENDP
END
The entry point may be different for your environment depending on whether you are creating a GUI or CONSOLE application and whether your project has a C/C++ file present.
Function names in the 64-bit calling convention are not required to start with an underscore unlike 32-bit Windows code.
How to link kernel32.lib and user32.lib using a combination of nasm and alink?
I'm following some tutorials on assembly programming and the guide wants me to execute the following commands:
nasm -fobj hello.asm
alink -oPE hello \lib\kernel32.lib \lib\user32.lib
The first command executes as expected, however the second command fails.
To link the .lib files, I've copied them from
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Lib
into my current folder.
The error messages I get when executing the second command is:
Loading file hello.obj
Loading file Kernel32.lib
2327 symbols
Loaded first linker member
Loading file User32.lib
1385 symbols
Loaded first linker member
matched Externs
matched ComDefs
Unresolved external MessageBoxA
Unresolved external ExitProcess
Now, I've two questions:
1) Where are kernel32.lib and user32.lib located?
2) How can I link these library files properly?
The operating system is Windows 10 (64-bit).
Update:
; Coded for NASM ;
; nasm -fobj hello.asm ;
; alink -oPE hello \lib\kernel32.lib \lib\user32.lib ;
;
extern MessageBoxA ; APIs used ;
extern ExitProcess ; in this file ;
;
[SECTION CODE USE32 CLASS=CODE] ; code section ;
..start: ; for the linker ;
;
push byte 0 ; only the buttons 'OK' ;
push dword caption ; caption of the BOX ;
push dword text ; text in the BOX ;
push byte 0 ; handle of the Box ;
call MessageBoxA ; print BOX on screen ;
;
push byte 0 ; ;
call ExitProcess ; EXIT ;
;
caption db "Your first WIN32 programm",0 ;
text db "HELLO",0 ;
;
end ; for the linker
I haven' found a kernel.lib or user.lib that can be used by ALINK. This may be due to the format of the needed .obj files, While the most Windows .obj's are formatted in COFF ALINK wants to be feeded with OMF.
A suitable WIN32.LIB is here. It includes MessageBoxA but not ExitProcess. It's not recommended to terminate a pure Windows program with a simple RET.
However, NASM can do the job as well if not better:
; Import the needed Win32 API functions.- http://www.nasm.us/doc/nasmdoc7.html#section-7.4.4
IMPORT ExitProcess kernel32.dll
IMPORT MessageBoxA user32.dll
; Still needed to be declared as external
EXTERN ExitProcess, MessageBoxA
[SECTION CODE USE32 CLASS=CODE] ; code section
..start:
push 0 ; only the buttons 'OK'
push dword caption ; caption of the BOX
push dword text ; text in the BOX
push 0 ; handle of the Box
call [MessageBoxA] ; print BOX on screen
push 0
call [ExitProcess]
caption db "Your first WIN32 programm",0
text db "HELLO",0
Please note that the functions are decorated with brackets when being called. Furthermore, it's better to place variables in a separate DATA section.
If you plan a huge project with a bunch of IMPORT's from a bunch of .DLL's tahe a look at the NASMX Project.
I've started to learn assembly and tried to compile the following code on visual studio 2010
DSEG SEGMENT
A DW 8
B DW 10
DSEG ENDS
SSEG SEGMENT STACK
DW 100H DUP(?)
SSEG ENDS
CSEG SEGMENT
ASSUME CS:CSEG, DS:DSEG, SS:SSEG
MAIN PROC FAR
PUSH DS
MOV AX, 0
PUSH AX
MOV AX, DSEG
MOV DS, AX
; The start of the program
MOV AX, A
MOV BX, B
ADD AX, BX
MOV A, AX
RET
MAIN ENDP
CSEG ENDS
END MAIN
I got the following errors:
1>main.asm(17): error A2004: symbol type conflict
1>main.asm(32): warning A4023: with /coff switch, leading underscore required for start address : MAIN
1>C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\BuildCustomizations\masm.targets(49,5): error MSB3721: The command "ml.exe /c /nologo /Zi /Fo"Debug\main.obj" /W3 /errorReport:prompt /coff /Tamain.asm" exited with code 1.
I searched the web for a soulution and the only thing I found is that error A2004 happes because the /coff directive.
How can I remove the /coff from the argument list? (If this is what cusing This error to apeare).
Thanks,
Ido Sorozon
If you are learning the assembly language basics, you should give a try with emu8086: it is a tool dedicated to assembly learning that features a Masm compatible assembler with support for macros (it can also support fasm syntax) and a 8086 cpu simulator with DOS screen emulation to test / debug your work.
It makes it possible to produce 16 bit COM programs, old fashioned EXEs and even boot sectors.
The sample program that you show in your question assembles without problem with that tool.
Contents
Intro
Code
Assembling and Running
Miscellaneous
Question
1. Intro
This isn't a question per se (though there is one at the bottom) but a HelloWorld app for people on StackOverflow to experiment with.
When I was first trying programing in MASM I tried to find a working HelloWorld application that used the WIN32 API calls (so not linking to C libraries) but couldn't find one (in MASM Syntax). So now that I have some experience I have written one for others wanting to learn assembly to fiddle with.
2. Code
.386 ; 386 Processor Instruction Set
.model flat,stdcall ; Flat memory model and stdcall method
option casemap:none ; Case Sensitive
;Libaries and Include files used in this project
; Windows.inc defines alias (such as NULL and STD_OUTPUT_HANDLE in this code
include \masm32\include\windows.inc
; Functions that we use (GetStdHandle, WriteConsole, and ExitProcess)
; Listing of all available functions in kernel32.lib
include \masm32\include\kernel32.inc
; Actuall byte code available of the functions
includelib \masm32\lib\kernel32.lib
.data
; Labels that with the allocated data (in this case Hello World!...) that are aliases to memory.
output db "Hello World!", 0ah, 0h; This String Hello World! and then a the newline character \n (0ah) and then the null character 0h
.code
start:
; --------------------------------------------------------------------------------------------------------------------------------------
; Retrieves that handle to the output console
;
; ====Arguments===
;
; STD_OUTPUT_HANDLE - alias for -11 and indicates that we want the handle to
; write to console output
;
invoke GetStdHandle, STD_OUTPUT_HANDLE
; --------------------------------------------------------------------------------------------------------------------------------------
; --------------------------------------------------------------------------------------------------------------------------------------
; Writes the text in output (.data section) to the console
;
; ====Arguments===
;
; eax - the handle to the console buffer
;
; addr output - pass by reference the text of output (Hello World!)
;
; sizeof output - the size of the string so that the WriteConsole knows when to
; stop (doesn't support NULL terminated strings I guess);
;
; ebx - secondary "return" value that contains the number of bytes written (eax
; is used for an error code)
;
; NULL - this is reserved and MSDN says just to pass NULL
;
; MSDN Link: http://msdn.microsoft.com/en-us/library/ms687401(v=VS.85).aspx
;
invoke WriteConsole, eax, addr output, sizeof output, ebx, NULL
; --------------------------------------------------------------------------------------------------------------------------------------
; --------------------------------------------------------------------------------------------------------------------------------------
; Exits the program with return code 0 (default one that usually is used to
; indicate that the program did not error
;
; ====Arguments===
;
; 0 - the exit code
;
; MSDN Link: http://msdn.microsoft.com/en-us/library/ms682658(VS.85).aspx
;
invoke ExitProcess, 0
; --------------------------------------------------------------------------------------------------------------------------------------
end start
3. Assembling and Running
I assume you have MASM32 installed in your C:\MASM32 directory.
If you do not have MASM installed
please go to
http://masm32.com/install.htm
and follow the instructions.
If MASM32 is installed in a different
directory please change the
instructions accordingly.
Open up the MASM32 Editor (QEditor) by either clicking on the Desktop Shortcut or if there is no shortcut go to C:\MASM32\ and double click qeditor.exe
Copy the code in the code section (only the text that has a gray background) and paste it into the MASM32 Editor (QEditor) and save it.
After saving the code click the Project menu and select Console Assemble and Link (NOT Assemble and Link (see Miscellaneous))
Go to START and click Run, then type cmd and hit ENTER a black box with gray text should appear
Navigate, using Explorer, to where you saved the code in step 3. There should now be a file with the same name as your source file (step 3) but be an exe. Drag and drop the exe file from the Explorer window to the cmd box (step 4 the black box)
Select the black box and hit ENTER, the text "Hello World!" should appear.
4. Miscellaneous
Why do I have to click Console Assemble and Run and not just Assemble and Run in the Project Menu?
The reason you have to click Console Assemble and Run is because there are two types of applications, there are GUIs and then there are text base console (DOS) applications. The Hello Would Application is a text based one and so when assembled must be have the settings a console based app would and not a GUI.
See the third paragraph under Remarks in this link for a more detailed explanation.
5. Question
Ok now the question, does anyone here see any problems, errors, or general issues with this code or have any suggestions
The program is fine. It is indeed "Hello World" version of Win32. However, remember its a console program. In Win32, you will be mostly dealing with Windows, Dialog Boxes and very less with Console (Incase, you want to deal specifically with console, thats another story).
If you want to lean Win32 Assembly, I strongly suggest you to look at Iczelion Tutorials.
Here is the "Hello World" to start with his tutorials:
http://win32assembly.online.fr/tut2.html
This sample code is simpler and easy to understand
.386
.model flat, stdcall
option casemap: none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data
szCaption db 'Hello', 0
szText db 'Hello, World!', 0
.code
start:
invoke MessageBox, NULL, offset szText, offset szCaption, MB_OK
invoke ExitProcess, NULL
end start
StdOut is a console function
You can use MessageBox function...
.model small,pascal,nearstack
.386
?WINPROLOGUE=1
include win.inc
includelib libw.lib
extern __astart:proc
.data
text sbyte "Hello f*** World!",0
title sbyte "Win",0
.code
WinMain PROC, hInstance:HANDLE, hPrevInstance:HANDLE, lpszCmdLine:LPSTR, nCmdShow,WORD
LOCAL msg:MSG
invoke MessageBox, NULL, addr text, addr title, 0
invoke PostQuitMessage,0
.while TRUE
invoke GetMessage,addr msg,NULL,0,0
.break .if (ax == 0)
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
.endw
WinMain ENDP
END __astart