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
7ad847bc
Commit
7ad847bc
authored
Nov 08, 2021
by
Eric Pouech
Committed by
Alexandre Julliard
Nov 08, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dbghelp/pdb: Handle S_LOCAL codeview entries.
Signed-off-by:
Eric Pouech
<
eric.pouech@gmail.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
de5fe893
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
181 additions
and
5 deletions
+181
-5
msc.c
dlls/dbghelp/msc.c
+178
-2
mscvpdb.h
include/wine/mscvpdb.h
+3
-3
No files found.
dlls/dbghelp/msc.c
View file @
7ad847bc
...
...
@@ -88,6 +88,8 @@ struct pdb_module_info
struct
pdb_file_info
pdb_files
[
CV_MAX_MODULES
];
};
#define loc_cv_local_range (loc_user + 0)
/* loc.offset contain the copy of all defrange* Codeview records following S_LOCAL */
/*========================================================================
* Debug file access helper routines
*/
...
...
@@ -1581,6 +1583,24 @@ static ULONG_PTR codeview_get_address(const struct msc_debug_info* msc_dbg,
codeview_map_offset
(
msc_dbg
,
sectp
[
seg
-
1
].
VirtualAddress
+
offset
);
}
static
BOOL
func_has_local
(
struct
symt_function
*
func
,
const
char
*
name
)
{
int
i
;
for
(
i
=
0
;
i
<
func
->
vchildren
.
num_elts
;
++
i
)
{
struct
symt
*
p
=
*
(
struct
symt
**
)
vector_at
(
&
func
->
vchildren
,
i
);
if
(
symt_check_tag
(
p
,
SymTagData
)
&&
!
strcmp
(((
struct
symt_data
*
)
p
)
->
hash_elt
.
name
,
name
))
return
TRUE
;
}
return
FALSE
;
}
static
const
union
codeview_symbol
*
get_next_sym
(
const
union
codeview_symbol
*
sym
)
{
return
(
const
union
codeview_symbol
*
)((
const
char
*
)
sym
+
sym
->
generic
.
len
+
2
);
}
static
inline
void
codeview_add_variable
(
const
struct
msc_debug_info
*
msc_dbg
,
struct
symt_compiland
*
compiland
,
const
char
*
name
,
...
...
@@ -1603,6 +1623,135 @@ static inline void codeview_add_variable(const struct msc_debug_info* msc_dbg,
}
}
struct
cv_local_info
{
unsigned
short
kind
;
/* the S_DEFRANGE* */
unsigned
short
ngaps
;
/* number of gaps */
unsigned
short
reg
;
unsigned
short
rangelen
;
/* after start */
short
offset
;
DWORD_PTR
start
;
struct
cv_addr_gap
gaps
[
0
];
};
static
const
struct
cv_addr_gap
*
codeview_get_gaps
(
const
union
codeview_symbol
*
symrange
)
{
const
struct
cv_addr_gap
*
gap
;
switch
(
symrange
->
generic
.
id
)
{
case
S_DEFRANGE
:
gap
=
symrange
->
defrange_v3
.
gaps
;
break
;
case
S_DEFRANGE_SUBFIELD
:
gap
=
symrange
->
defrange_subfield_v3
.
gaps
;
break
;
case
S_DEFRANGE_REGISTER
:
gap
=
symrange
->
defrange_register_v3
.
gaps
;
break
;
case
S_DEFRANGE_FRAMEPOINTER_REL
:
gap
=
symrange
->
defrange_frameptrrel_v3
.
gaps
;
break
;
case
S_DEFRANGE_SUBFIELD_REGISTER
:
gap
=
symrange
->
defrange_subfield_register_v3
.
gaps
;
break
;
case
S_DEFRANGE_REGISTER_REL
:
gap
=
symrange
->
defrange_registerrel_v3
.
gaps
;
break
;
/* no gaps for that one */
case
S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
default:
return
NULL
;
}
return
gap
!=
(
const
struct
cv_addr_gap
*
)
get_next_sym
(
symrange
)
?
gap
:
NULL
;
}
static
void
codeview_xform_range
(
const
struct
msc_debug_info
*
msc_dbg
,
struct
cv_local_info
*
locinfo
,
const
struct
cv_addr_range
*
adrange
)
{
locinfo
->
start
=
codeview_get_address
(
msc_dbg
,
adrange
->
isectStart
,
adrange
->
offStart
);
locinfo
->
rangelen
=
adrange
->
cbRange
;
}
static
unsigned
codeview_transform_defrange
(
const
struct
msc_debug_info
*
msc_dbg
,
struct
symt_function
*
curr_func
,
const
union
codeview_symbol
*
sym
,
struct
location
*
loc
)
{
const
union
codeview_symbol
*
first_symrange
=
get_next_sym
(
sym
);
const
union
codeview_symbol
*
symrange
;
const
struct
cv_addr_gap
*
gap
;
unsigned
len
,
alloc
=
sizeof
(
DWORD
);
/* for terminating kind = 0 */
unsigned
char
*
ptr
;
/* we need to transform the cv_addr_range into cv_local_info */
for
(
symrange
=
first_symrange
;
symrange
->
generic
.
id
>=
S_DEFRANGE
&&
symrange
->
generic
.
id
<=
S_DEFRANGE_REGISTER_REL
;
symrange
=
get_next_sym
(
symrange
))
{
gap
=
codeview_get_gaps
(
symrange
);
alloc
+=
sizeof
(
struct
cv_local_info
)
+
(
gap
?
(
const
char
*
)
get_next_sym
(
symrange
)
-
(
const
char
*
)
gap
:
0
);
}
/* total length of all S_DEFRANGE* records (in bytes) following S_LOCAL */
len
=
(
const
char
*
)
symrange
-
(
const
char
*
)
first_symrange
;
ptr
=
pool_alloc
(
&
msc_dbg
->
module
->
pool
,
alloc
);
if
(
ptr
)
{
struct
cv_local_info
*
locinfo
=
(
struct
cv_local_info
*
)
ptr
;
loc
->
kind
=
loc_cv_local_range
;
loc
->
offset
=
(
DWORD_PTR
)
ptr
;
/* transform the cv_addr_range into cv_local_info */
for
(
symrange
=
first_symrange
;
symrange
->
generic
.
id
>=
S_DEFRANGE
&&
symrange
->
generic
.
id
<=
S_DEFRANGE_REGISTER_REL
;
symrange
=
get_next_sym
(
symrange
))
{
locinfo
->
kind
=
symrange
->
generic
.
id
;
switch
(
symrange
->
generic
.
id
)
{
case
S_DEFRANGE
:
case
S_DEFRANGE_SUBFIELD
:
/* FIXME: transformation unsupported; let loc_compute bark if actually needed */
break
;
case
S_DEFRANGE_REGISTER
:
locinfo
->
reg
=
symrange
->
defrange_register_v3
.
reg
;
codeview_xform_range
(
msc_dbg
,
locinfo
,
&
symrange
->
defrange_register_v3
.
range
);
break
;
case
S_DEFRANGE_FRAMEPOINTER_REL
:
locinfo
->
offset
=
symrange
->
defrange_frameptrrel_v3
.
offFramePointer
;
codeview_xform_range
(
msc_dbg
,
locinfo
,
&
symrange
->
defrange_frameptrrel_v3
.
range
);
break
;
case
S_DEFRANGE_SUBFIELD_REGISTER
:
locinfo
->
reg
=
symrange
->
defrange_subfield_register_v3
.
reg
;
locinfo
->
offset
=
symrange
->
defrange_subfield_register_v3
.
offParent
;
codeview_xform_range
(
msc_dbg
,
locinfo
,
&
symrange
->
defrange_subfield_register_v3
.
range
);
break
;
case
S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
:
locinfo
->
offset
=
symrange
->
defrange_frameptr_relfullscope_v3
.
offFramePointer
;
locinfo
->
start
=
curr_func
->
address
;
locinfo
->
rangelen
=
curr_func
->
size
;
break
;
case
S_DEFRANGE_REGISTER_REL
:
locinfo
->
reg
=
symrange
->
defrange_registerrel_v3
.
baseReg
;
locinfo
->
offset
=
symrange
->
defrange_registerrel_v3
.
offBasePointer
;
codeview_xform_range
(
msc_dbg
,
locinfo
,
&
symrange
->
defrange_registerrel_v3
.
range
);
break
;
default:
assert
(
0
);
}
gap
=
codeview_get_gaps
(
symrange
);
if
(
gap
)
{
unsigned
gaplen
=
(
const
char
*
)
get_next_sym
(
symrange
)
-
(
const
char
*
)
gap
;
locinfo
->
ngaps
=
gaplen
/
sizeof
(
*
gap
);
memcpy
(
locinfo
->
gaps
,
gap
,
gaplen
);
locinfo
=
(
struct
cv_local_info
*
)((
unsigned
char
*
)(
locinfo
+
1
)
+
gaplen
);
}
else
{
locinfo
->
ngaps
=
0
;
locinfo
++
;
}
}
*
(
DWORD
*
)
locinfo
=
0
;
/* store terminating kind == 0 */
}
else
{
loc
->
kind
=
loc_error
;
loc
->
reg
=
loc_err_internal
;
}
return
len
;
}
static
BOOL
codeview_snarf
(
const
struct
msc_debug_info
*
msc_dbg
,
const
BYTE
*
root
,
int
offset
,
int
size
,
BOOL
do_globals
)
{
...
...
@@ -1774,6 +1923,8 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo
terminate_string
(
&
sym
->
stack_v2
.
p_name
));
break
;
case
S_BPREL32
:
/* S_BPREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
if
(
func_has_local
(
curr_func
,
sym
->
stack_v3
.
name
))
break
;
loc
.
kind
=
loc_regrel
;
/* Yes, it's i386 dependent, but that's the symbol purpose. S_REGREL is used on other CPUs */
loc
.
reg
=
CV_REG_EBP
;
...
...
@@ -1785,6 +1936,8 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo
sym
->
stack_v3
.
name
);
break
;
case
S_REGREL32
:
/* S_REGREL32 can be present after S_LOCAL; prefer S_LOCAL when present */
if
(
func_has_local
(
curr_func
,
sym
->
regrel_v3
.
name
))
break
;
loc
.
kind
=
loc_regrel
;
loc
.
reg
=
sym
->
regrel_v3
.
reg
;
loc
.
offset
=
sym
->
regrel_v3
.
offset
;
...
...
@@ -1815,6 +1968,8 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo
terminate_string
(
&
sym
->
register_v2
.
p_name
));
break
;
case
S_REGISTER
:
/* S_REGISTER can be present after S_LOCAL; prefer S_LOCAL when present */
if
(
func_has_local
(
curr_func
,
sym
->
register_v3
.
name
))
break
;
loc
.
kind
=
loc_register
;
loc
.
reg
=
sym
->
register_v3
.
reg
;
loc
.
offset
=
0
;
...
...
@@ -1989,6 +2144,14 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo
sym
->
udt_v3
.
name
,
sym
->
udt_v3
.
type
);
}
break
;
case
S_LOCAL
:
length
+=
codeview_transform_defrange
(
msc_dbg
,
curr_func
,
sym
,
&
loc
);
symt_add_func_local
(
msc_dbg
->
module
,
curr_func
,
sym
->
local_v3
.
varflags
&
0x0001
?
DataIsParam
:
DataIsLocal
,
&
loc
,
block
,
codeview_get_type
(
sym
->
local_v3
.
symtype
,
FALSE
),
sym
->
local_v3
.
name
);
break
;
/*
* These are special, in that they are always followed by an
...
...
@@ -2027,8 +2190,11 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo
case
S_SECTION
:
case
S_COFFGROUP
:
case
S_EXPORT
:
case
S_LOCAL
:
case
S_CALLSITEINFO
:
/* even if S_LOCAL groks all the S_DEFRANGE* records following itself,
* those kinds of records can also be present after a S_FILESTATIC record
* so silence them until (at least) S_FILESTATIC is supported
*/
case
S_DEFRANGE_REGISTER
:
case
S_DEFRANGE_FRAMEPOINTER_REL
:
case
S_DEFRANGE_SUBFIELD_REGISTER
:
...
...
@@ -2054,6 +2220,16 @@ static BOOL codeview_snarf(const struct msc_debug_info* msc_dbg, const BYTE* roo
return
TRUE
;
}
static
void
pdb_location_compute
(
struct
process
*
pcs
,
const
struct
module_format
*
modfmt
,
const
struct
symt_function
*
func
,
struct
location
*
loc
)
{
loc
->
kind
=
loc_register
;
loc
->
reg
=
loc_err_internal
;
}
static
BOOL
codeview_snarf_public
(
const
struct
msc_debug_info
*
msc_dbg
,
const
BYTE
*
root
,
int
offset
,
int
size
)
...
...
@@ -2886,7 +3062,7 @@ static BOOL pdb_process_file(const struct process* pcs,
msc_dbg
->
module
->
format_info
[
DFI_PDB
]
=
modfmt
;
modfmt
->
module
=
msc_dbg
->
module
;
modfmt
->
remove
=
pdb_module_remove
;
modfmt
->
loc_compute
=
NULL
;
modfmt
->
loc_compute
=
pdb_location_compute
;
modfmt
->
u
.
pdb_info
=
pdb_module_info
;
memset
(
cv_zmodules
,
0
,
sizeof
(
cv_zmodules
));
...
...
include/wine/mscvpdb.h
View file @
7ad847bc
...
...
@@ -1879,7 +1879,7 @@ union codeview_symbol
{
unsigned
short
int
len
;
unsigned
short
int
id
;
unsigned
int
offFramePointer
;
int
offFramePointer
;
struct
cv_addr_range
range
;
struct
cv_addr_gap
gaps
[
0
];
}
defrange_frameptrrel_v3
;
...
...
@@ -1888,7 +1888,7 @@ union codeview_symbol
{
unsigned
short
int
len
;
unsigned
short
int
id
;
unsigned
int
offFramePointer
;
int
offFramePointer
;
}
defrange_frameptr_relfullscope_v3
;
struct
...
...
@@ -1911,7 +1911,7 @@ union codeview_symbol
unsigned
short
spilledUdtMember
:
1
;
unsigned
short
padding
:
3
;
unsigned
short
offsetParent
:
12
;
unsigned
int
offBasePointer
;
int
offBasePointer
;
struct
cv_addr_range
range
;
struct
cv_addr_gap
gaps
[
0
];
}
defrange_registerrel_v3
;
...
...
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