Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
99439e75
Commit
99439e75
authored
Jan 08, 2011
by
Eric Pouech
Committed by
Alexandre Julliard
Jan 10, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dbghelp: Added preliminary extended FPO information out of PDB files.
parent
5ce195ae
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
340 additions
and
2 deletions
+340
-2
cpu_i386.c
dlls/dbghelp/cpu_i386.c
+30
-2
dbghelp_private.h
dlls/dbghelp/dbghelp_private.h
+6
-0
msc.c
dlls/dbghelp/msc.c
+304
-0
No files found.
dlls/dbghelp/cpu_i386.c
View file @
99439e75
...
...
@@ -214,7 +214,8 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
#ifdef __i386__
if
(
curr_mode
==
stm_32bit
)
{
DWORD_PTR
xframe
;
DWORD_PTR
xframe
;
struct
pdb_cmd_pair
cpair
[
4
];
if
(
dwarf2_virtual_unwind
(
csw
,
frame
->
AddrPC
.
Offset
-
deltapc
,
context
,
&
xframe
))
{
...
...
@@ -224,6 +225,19 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
frame
->
AddrReturn
.
Offset
=
context
->
Eip
;
goto
done_pep
;
}
cpair
[
0
].
name
=
"$ebp"
;
cpair
[
0
].
pvalue
=
&
context
->
Ebp
;
cpair
[
1
].
name
=
"$esp"
;
cpair
[
1
].
pvalue
=
&
context
->
Esp
;
cpair
[
2
].
name
=
"$eip"
;
cpair
[
2
].
pvalue
=
&
context
->
Eip
;
cpair
[
3
].
name
=
NULL
;
cpair
[
3
].
pvalue
=
NULL
;
if
(
pdb_virtual_unwind
(
csw
,
frame
->
AddrPC
.
Offset
-
deltapc
,
context
,
cpair
))
{
frame
->
AddrStack
.
Mode
=
frame
->
AddrFrame
.
Mode
=
frame
->
AddrReturn
.
Mode
=
AddrModeFlat
;
frame
->
AddrStack
.
Offset
=
context
->
Esp
;
frame
->
AddrFrame
.
Offset
=
context
->
Ebp
;
frame
->
AddrReturn
.
Offset
=
context
->
Eip
;
goto
done_pep
;
}
}
#endif
}
...
...
@@ -353,7 +367,8 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
else
{
#ifdef __i386__
DWORD_PTR
xframe
;
DWORD_PTR
xframe
;
struct
pdb_cmd_pair
cpair
[
4
];
if
(
dwarf2_virtual_unwind
(
csw
,
frame
->
AddrPC
.
Offset
-
deltapc
,
context
,
&
xframe
))
{
...
...
@@ -363,6 +378,19 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CO
frame
->
AddrReturn
.
Offset
=
context
->
Eip
;
goto
done_pep
;
}
cpair
[
0
].
name
=
"$ebp"
;
cpair
[
0
].
pvalue
=
&
context
->
Ebp
;
cpair
[
1
].
name
=
"$esp"
;
cpair
[
1
].
pvalue
=
&
context
->
Esp
;
cpair
[
2
].
name
=
"$eip"
;
cpair
[
2
].
pvalue
=
&
context
->
Eip
;
cpair
[
3
].
name
=
NULL
;
cpair
[
3
].
pvalue
=
NULL
;
if
(
pdb_virtual_unwind
(
csw
,
frame
->
AddrPC
.
Offset
-
deltapc
,
context
,
cpair
))
{
frame
->
AddrStack
.
Mode
=
frame
->
AddrFrame
.
Mode
=
frame
->
AddrReturn
.
Mode
=
AddrModeFlat
;
frame
->
AddrStack
.
Offset
=
context
->
Esp
;
frame
->
AddrFrame
.
Offset
=
context
->
Ebp
;
frame
->
AddrReturn
.
Offset
=
context
->
Eip
;
goto
done_pep
;
}
#endif
frame
->
AddrStack
.
Offset
=
frame
->
AddrFrame
.
Offset
+
2
*
sizeof
(
DWORD
);
/* "pop up" previous EBP value */
...
...
dlls/dbghelp/dbghelp_private.h
View file @
99439e75
...
...
@@ -559,6 +559,12 @@ extern BOOL pe_load_debug_directory(const struct process* pcs,
const
IMAGE_SECTION_HEADER
*
sectp
,
DWORD
nsect
,
const
IMAGE_DEBUG_DIRECTORY
*
dbg
,
int
nDbg
);
extern
BOOL
pdb_fetch_file_info
(
const
struct
pdb_lookup
*
pdb_lookup
,
unsigned
*
matched
);
struct
pdb_cmd_pair
{
const
char
*
name
;
DWORD
*
pvalue
;
};
extern
BOOL
pdb_virtual_unwind
(
struct
cpu_stack_walk
*
csw
,
DWORD_PTR
ip
,
CONTEXT
*
context
,
struct
pdb_cmd_pair
*
cpair
);
/* path.c */
extern
BOOL
path_find_symbol_file
(
const
struct
process
*
pcs
,
PCSTR
full_path
,
...
...
dlls/dbghelp/msc.c
View file @
99439e75
...
...
@@ -2750,6 +2750,310 @@ BOOL pdb_fetch_file_info(const struct pdb_lookup* pdb_lookup, unsigned* matched)
}
/*========================================================================
* FPO unwinding code
*/
/* Stack unwinding is based on postfixed operations.
* Let's define our Postfix EValuator
*/
#define PEV_MAX_LEN 32
struct
pevaluator
{
struct
cpu_stack_walk
*
csw
;
struct
pool
pool
;
struct
vector
stack
;
unsigned
stk_index
;
struct
hash_table
values
;
char
error
[
64
];
};
struct
zvalue
{
DWORD_PTR
value
;
struct
hash_table_elt
elt
;
};
#define PEV_ERROR(pev, msg) snprintf((pev)->error, sizeof((pev)->error), "%s", (msg)),FALSE
#define PEV_ERROR1(pev, msg, pmt) snprintf((pev)->error, sizeof((pev)->error), (msg), (pmt)),FALSE
#if 0
static void pev_dump_stack(struct pevaluator* pev)
{
unsigned i;
FIXME("stack #%d\n", pev->stk_index);
for (i = 0; i < pev->stk_index; i++)
{
FIXME("\t%d) %s\n", i, *(char**)vector_at(&pev->stack, i));
}
}
#endif
/* get the value out of an operand (variable or literal) */
static
BOOL
pev_get_val
(
struct
pevaluator
*
pev
,
const
char
*
str
,
DWORD_PTR
*
val
)
{
char
*
n
;
struct
hash_table_iter
hti
;
void
*
ptr
;
switch
(
str
[
0
])
{
case
'$'
:
case
'.'
:
hash_table_iter_init
(
&
pev
->
values
,
&
hti
,
str
);
if
(
!
(
ptr
=
hash_table_iter_up
(
&
hti
)))
return
PEV_ERROR1
(
pev
,
"get_zvalue: no value found (%s)"
,
str
);
*
val
=
GET_ENTRY
(
ptr
,
struct
zvalue
,
elt
)
->
value
;
return
TRUE
;
default:
*
val
=
strtol
(
str
,
&
n
,
10
);
if
(
n
==
str
||
*
n
!=
'\0'
)
return
PEV_ERROR1
(
pev
,
"get_val: not a literal (%s)"
,
str
);
return
TRUE
;
}
}
/* push an operand onto the stack */
static
BOOL
pev_push
(
struct
pevaluator
*
pev
,
const
char
*
elt
)
{
char
**
at
;
if
(
pev
->
stk_index
<
vector_length
(
&
pev
->
stack
))
at
=
vector_at
(
&
pev
->
stack
,
pev
->
stk_index
);
else
at
=
vector_add
(
&
pev
->
stack
,
&
pev
->
pool
);
if
(
!
at
)
return
PEV_ERROR
(
pev
,
"push: out of memory"
);
*
at
=
pool_strdup
(
&
pev
->
pool
,
elt
);
pev
->
stk_index
++
;
return
TRUE
;
}
/* pop an operand from the stack */
static
BOOL
pev_pop
(
struct
pevaluator
*
pev
,
char
*
elt
)
{
char
**
at
=
vector_at
(
&
pev
->
stack
,
--
pev
->
stk_index
);
if
(
!
at
)
return
PEV_ERROR
(
pev
,
"pop: stack empty"
);
strcpy
(
elt
,
*
at
);
return
TRUE
;
}
/* pop an operand from the stack, and gets its value */
static
BOOL
pev_pop_val
(
struct
pevaluator
*
pev
,
DWORD_PTR
*
val
)
{
char
p
[
PEV_MAX_LEN
];
return
pev_pop
(
pev
,
p
)
&&
pev_get_val
(
pev
,
p
,
val
);
}
/* set var 'name' a new value (creates the var if it doesn't exist) */
static
BOOL
pev_set_value
(
struct
pevaluator
*
pev
,
const
char
*
name
,
DWORD_PTR
val
)
{
struct
hash_table_iter
hti
;
void
*
ptr
;
hash_table_iter_init
(
&
pev
->
values
,
&
hti
,
name
);
if
(
!
(
ptr
=
hash_table_iter_up
(
&
hti
)))
{
struct
zvalue
*
zv
=
pool_alloc
(
&
pev
->
pool
,
sizeof
(
*
zv
));
if
(
!
zv
)
return
PEV_ERROR
(
pev
,
"set_value: out of memory"
);
zv
->
value
=
val
;
zv
->
elt
.
name
=
pool_strdup
(
&
pev
->
pool
,
name
);
hash_table_add
(
&
pev
->
values
,
&
zv
->
elt
);
}
else
GET_ENTRY
(
ptr
,
struct
zvalue
,
elt
)
->
value
=
val
;
return
TRUE
;
}
/* execute a binary operand from the two top most values on the stack.
* puts result on top of the stack */
static
BOOL
pev_binop
(
struct
pevaluator
*
pev
,
char
op
)
{
char
res
[
PEV_MAX_LEN
];
DWORD_PTR
v1
,
v2
,
c
;
if
(
!
pev_pop_val
(
pev
,
&
v1
)
||
!
pev_pop_val
(
pev
,
&
v2
))
return
FALSE
;
switch
(
op
)
{
case
'+'
:
c
=
v1
+
v2
;
break
;
case
'-'
:
c
=
v1
-
v2
;
break
;
case
'*'
:
c
=
v1
*
v2
;
break
;
case
'/'
:
c
=
v1
/
v2
;
break
;
case
'%'
:
c
=
v1
%
v2
;
break
;
default:
return
PEV_ERROR1
(
pev
,
"binop: unknown op (%c)"
,
op
);
}
snprintf
(
res
,
sizeof
(
res
),
"%ld"
,
c
);
pev_push
(
pev
,
res
);
return
TRUE
;
}
/* pops top most operand, dereference it, on pushes the result on top of the stack */
static
BOOL
pev_deref
(
struct
pevaluator
*
pev
)
{
char
res
[
PEV_MAX_LEN
];
DWORD_PTR
v1
,
v2
;
if
(
!
pev_pop_val
(
pev
,
&
v1
))
return
FALSE
;
if
(
!
sw_read_mem
(
pev
->
csw
,
v1
,
&
v2
,
sizeof
(
v2
)))
return
PEV_ERROR1
(
pev
,
"deref: cannot read mem at %lx
\n
"
,
v1
);
snprintf
(
res
,
sizeof
(
res
),
"%ld"
,
v2
);
pev_push
(
pev
,
res
);
return
TRUE
;
}
/* assign value to variable (from two top most operands) */
static
BOOL
pev_assign
(
struct
pevaluator
*
pev
)
{
char
p2
[
PEV_MAX_LEN
];
DWORD_PTR
v1
;
if
(
!
pev_pop_val
(
pev
,
&
v1
)
||
!
pev_pop
(
pev
,
p2
))
return
FALSE
;
if
(
p2
[
0
]
!=
'$'
)
return
PEV_ERROR1
(
pev
,
"assign: %s isn't a variable"
,
p2
);
pev_set_value
(
pev
,
p2
,
v1
);
return
TRUE
;
}
/* initializes the postfix evaluator */
static
void
pev_init
(
struct
pevaluator
*
pev
,
struct
cpu_stack_walk
*
csw
,
PDB_FPO_DATA
*
fpoext
,
struct
pdb_cmd_pair
*
cpair
)
{
pev
->
csw
=
csw
;
pool_init
(
&
pev
->
pool
,
512
);
vector_init
(
&
pev
->
stack
,
sizeof
(
char
*
),
8
);
pev
->
stk_index
=
0
;
hash_table_init
(
&
pev
->
pool
,
&
pev
->
values
,
8
);
pev
->
error
[
0
]
=
'\0'
;
for
(;
cpair
->
name
;
cpair
++
)
pev_set_value
(
pev
,
cpair
->
name
,
*
cpair
->
pvalue
);
pev_set_value
(
pev
,
".raSearchStart"
,
fpoext
->
start
);
pev_set_value
(
pev
,
".cbLocals"
,
fpoext
->
locals_size
);
pev_set_value
(
pev
,
".cbParams"
,
fpoext
->
params_size
);
pev_set_value
(
pev
,
".cbSavedRegs"
,
fpoext
->
savedregs_size
);
}
static
BOOL
pev_free
(
struct
pevaluator
*
pev
,
struct
pdb_cmd_pair
*
cpair
)
{
DWORD_PTR
val
;
if
(
cpair
)
for
(;
cpair
->
name
;
cpair
++
)
{
if
(
pev_get_val
(
pev
,
cpair
->
name
,
&
val
))
*
cpair
->
pvalue
=
val
;
}
pool_destroy
(
&
pev
->
pool
);
return
TRUE
;
}
static
BOOL
pdb_parse_cmd_string
(
struct
cpu_stack_walk
*
csw
,
PDB_FPO_DATA
*
fpoext
,
const
char
*
cmd
,
struct
pdb_cmd_pair
*
cpair
)
{
char
token
[
PEV_MAX_LEN
];
char
*
ptok
=
token
;
const
char
*
ptr
;
BOOL
over
=
FALSE
;
struct
pevaluator
pev
;
pev_init
(
&
pev
,
csw
,
fpoext
,
cpair
);
for
(
ptr
=
cmd
;
!
over
;
ptr
++
)
{
if
(
*
ptr
==
' '
||
(
over
=
*
ptr
==
'\0'
))
{
*
ptok
=
'\0'
;
if
(
!
strcmp
(
token
,
"+"
)
||
!
strcmp
(
token
,
"-"
)
||
!
strcmp
(
token
,
"*"
)
||
!
strcmp
(
token
,
"/"
)
||
!
strcmp
(
token
,
"%"
))
{
if
(
!
pev_binop
(
&
pev
,
token
[
0
]))
goto
done
;
}
else
if
(
!
strcmp
(
token
,
"^"
))
{
if
(
!
pev_deref
(
&
pev
))
goto
done
;
}
else
if
(
!
strcmp
(
token
,
"="
))
{
if
(
!
pev_assign
(
&
pev
))
goto
done
;
}
else
{
if
(
!
pev_push
(
&
pev
,
token
))
goto
done
;
}
ptok
=
token
;
}
else
{
if
(
ptok
-
token
>=
PEV_MAX_LEN
-
1
)
{
PEV_ERROR1
(
&
pev
,
"parse: token too long (%s)"
,
ptr
-
(
ptok
-
token
));
goto
done
;
}
*
ptok
++
=
*
ptr
;
}
}
pev_free
(
&
pev
,
cpair
);
return
TRUE
;
done:
FIXME
(
"Couldn't evaluate %s => %s
\n
"
,
wine_dbgstr_a
(
cmd
),
pev
.
error
);
pev_free
(
&
pev
,
NULL
);
return
FALSE
;
}
BOOL
pdb_virtual_unwind
(
struct
cpu_stack_walk
*
csw
,
DWORD_PTR
ip
,
CONTEXT
*
context
,
struct
pdb_cmd_pair
*
cpair
)
{
struct
module_pair
pair
;
struct
pdb_module_info
*
pdb_info
;
PDB_FPO_DATA
*
fpoext
;
unsigned
i
,
size
,
strsize
;
char
*
strbase
;
BOOL
ret
=
TRUE
;
if
(
!
(
pair
.
pcs
=
process_find_by_handle
(
csw
->
hProcess
))
||
!
(
pair
.
requested
=
module_find_by_addr
(
pair
.
pcs
,
ip
,
DMT_UNKNOWN
))
||
!
module_get_debug
(
&
pair
))
return
FALSE
;
if
(
!
pair
.
effective
->
format_info
[
DFI_PDB
])
return
FALSE
;
pdb_info
=
pair
.
effective
->
format_info
[
DFI_PDB
]
->
u
.
pdb_info
;
TRACE
(
"searching %lx => %lx
\n
"
,
ip
,
ip
-
(
DWORD_PTR
)
pair
.
effective
->
module
.
BaseOfImage
);
ip
-=
(
DWORD_PTR
)
pair
.
effective
->
module
.
BaseOfImage
;
strbase
=
pdb_read_file
(
&
pdb_info
->
pdb_files
[
0
],
12
);
/* FIXME: really fixed index ??? */
if
(
!
strbase
)
return
FALSE
;
if
(
*
(
const
DWORD
*
)
strbase
!=
0xeffeeffe
)
{
pdb_free
(
strbase
);
return
FALSE
;
}
strsize
=
*
(
const
DWORD
*
)(
strbase
+
8
);
fpoext
=
pdb_read_file
(
&
pdb_info
->
pdb_files
[
0
],
10
);
size
=
pdb_get_file_size
(
&
pdb_info
->
pdb_files
[
0
],
10
);
if
(
fpoext
&&
(
size
%
sizeof
(
*
fpoext
))
==
0
)
{
size
/=
sizeof
(
*
fpoext
);
for
(
i
=
0
;
i
<
size
;
i
++
)
{
if
(
fpoext
[
i
].
start
<=
ip
&&
ip
<
fpoext
[
i
].
start
+
fpoext
[
i
].
func_size
)
{
TRACE
(
"
\t
%08x %08x %8x %8x %4x %4x %4x %08x %s
\n
"
,
fpoext
[
i
].
start
,
fpoext
[
i
].
func_size
,
fpoext
[
i
].
locals_size
,
fpoext
[
i
].
params_size
,
fpoext
[
i
].
maxstack_size
,
fpoext
[
i
].
prolog_size
,
fpoext
[
i
].
savedregs_size
,
fpoext
[
i
].
flags
,
fpoext
[
i
].
str_offset
<
strsize
?
wine_dbgstr_a
(
strbase
+
12
+
fpoext
[
i
].
str_offset
)
:
"<out of bounds>"
);
if
(
fpoext
[
i
].
str_offset
<
strsize
)
ret
=
pdb_parse_cmd_string
(
csw
,
fpoext
,
strbase
+
12
+
fpoext
[
i
].
str_offset
,
cpair
);
else
ret
=
FALSE
;
break
;
}
}
}
else
ret
=
FALSE
;
pdb_free
(
fpoext
);
pdb_free
(
strbase
);
return
ret
;
}
/*========================================================================
* Process CodeView debug information.
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment