Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
4228e622
Commit
4228e622
authored
Oct 24, 2010
by
Luuk van Dijk
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
6l/8l: global and local variables and type info.
R=rsc CC=golang-dev
https://golang.org/cl/2201044
parent
c28fa513
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
1040 additions
and
86 deletions
+1040
-86
dwarf.c
src/cmd/ld/dwarf.c
+1017
-75
dwarf.h
src/cmd/ld/dwarf.h
+7
-7
dwarf_defs.h
src/cmd/ld/dwarf_defs.h
+14
-2
elf.h
src/cmd/ld/elf.h
+1
-2
type.go
src/pkg/runtime/type.go
+1
-0
No files found.
src/cmd/ld/dwarf.c
View file @
4228e622
...
@@ -2,6 +2,15 @@
...
@@ -2,6 +2,15 @@
// Use of this source code is governed by a BSD-style
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// license that can be found in the LICENSE file.
// TODO:
// - eliminate DW_CLS_ if not used
// - package info in compilation units
// - assign global variables and types to their packages
// - (upstream) type info for C parts of runtime
// - gdb uses c syntax, meaning clumsy quoting is needed for go identifiers. eg
// ptype struct '[]uint8' and qualifiers need to be quoted away
// - lexical scoping is lost, so gdb gets confused as to which 'main.i' you mean.
//
#include "l.h"
#include "l.h"
#include "lib.h"
#include "lib.h"
#include "../ld/dwarf.h"
#include "../ld/dwarf.h"
...
@@ -17,10 +26,16 @@ static vlong abbrevo;
...
@@ -17,10 +26,16 @@ static vlong abbrevo;
static
vlong
abbrevsize
;
static
vlong
abbrevsize
;
static
vlong
lineo
;
static
vlong
lineo
;
static
vlong
linesize
;
static
vlong
linesize
;
static
vlong
infoo
;
static
vlong
infoo
;
// also the base for DWDie->offs and reference attributes.
static
vlong
infosize
;
static
vlong
infosize
;
static
vlong
frameo
;
static
vlong
frameo
;
static
vlong
framesize
;
static
vlong
framesize
;
static
vlong
pubnameso
;
static
vlong
pubnamessize
;
static
vlong
pubtypeso
;
static
vlong
pubtypessize
;
static
vlong
arangeso
;
static
vlong
arangessize
;
/*
/*
* Basic I/O
* Basic I/O
...
@@ -39,7 +54,6 @@ addrput(vlong addr)
...
@@ -39,7 +54,6 @@ addrput(vlong addr)
}
}
}
}
static
int
static
int
uleb128enc
(
uvlong
v
,
char
*
dst
)
uleb128enc
(
uvlong
v
,
char
*
dst
)
{
{
...
@@ -106,17 +120,34 @@ struct DWAttrForm {
...
@@ -106,17 +120,34 @@ struct DWAttrForm {
uint8
form
;
uint8
form
;
};
};
// index into the abbrevs table below.
// Index into the abbrevs table below.
// Keep in sync with ispubname() and ispubtype() below.
enum
enum
{
{
DW_ABRV_NULL
,
DW_ABRV_NULL
,
DW_ABRV_COMPUNIT
,
DW_ABRV_COMPUNIT
,
DW_ABRV_FUNCTION
,
DW_ABRV_FUNCTION
,
DW_ABRV_VARIABLE
,
DW_ABRV_AUTO
,
DW_ABRV_PARAM
,
DW_ABRV_STRUCTFIELD
,
DW_ABRV_NULLTYPE
,
DW_ABRV_BASETYPE
,
DW_ABRV_ARRAYTYPE
,
DW_ABRV_CHANTYPE
,
DW_ABRV_FUNCTYPE
,
DW_ABRV_IFACETYPE
,
DW_ABRV_MAPTYPE
,
DW_ABRV_PTRTYPE
,
DW_ABRV_SLICETYPE
,
DW_ABRV_STRINGTYPE
,
DW_ABRV_STRUCTTYPE
,
DW_ABRV_TYPEDECL
,
DW_NABRV
DW_NABRV
};
};
typedef
struct
DWAbbrev
DWAbbrev
;
typedef
struct
DWAbbrev
DWAbbrev
;
struct
DWAbbrev
{
st
atic
st
ruct
DWAbbrev
{
uint8
tag
;
uint8
tag
;
uint8
children
;
uint8
children
;
DWAttrForm
attr
[
30
];
DWAttrForm
attr
[
30
];
...
@@ -135,10 +166,137 @@ struct DWAbbrev {
...
@@ -135,10 +166,137 @@ struct DWAbbrev {
},
},
/* FUNCTION */
/* FUNCTION */
{
{
DW_TAG_subprogram
,
DW_CHILDREN_
no
,
DW_TAG_subprogram
,
DW_CHILDREN_
yes
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_low_pc
,
DW_FORM_addr
,
DW_AT_low_pc
,
DW_FORM_addr
,
DW_AT_high_pc
,
DW_FORM_addr
,
DW_AT_high_pc
,
DW_FORM_addr
,
DW_AT_external
,
DW_FORM_flag
,
0
,
0
},
/* VARIABLE */
{
DW_TAG_variable
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_location
,
DW_FORM_addr
,
DW_AT_type
,
DW_FORM_ref_addr
,
DW_AT_external
,
DW_FORM_flag
,
0
,
0
},
/* AUTO */
{
DW_TAG_variable
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_location
,
DW_FORM_block1
,
DW_AT_type
,
DW_FORM_ref_addr
,
0
,
0
},
/* PARAM */
{
DW_TAG_formal_parameter
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_location
,
DW_FORM_block1
,
DW_AT_type
,
DW_FORM_ref_addr
,
0
,
0
},
/* STRUCTFIELD */
{
DW_TAG_member
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_data_member_location
,
DW_FORM_block1
,
DW_AT_type
,
DW_FORM_ref_addr
,
0
,
0
},
/* NULLTYPE */
{
DW_TAG_unspecified_type
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
0
,
0
},
/* BASETYPE */
{
DW_TAG_base_type
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_encoding
,
DW_FORM_data1
,
DW_AT_byte_size
,
DW_FORM_data1
,
0
,
0
},
/* ARRAYTYPE */
{
DW_TAG_array_type
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_type
,
DW_FORM_ref_addr
,
DW_AT_byte_size
,
DW_FORM_udata
,
0
,
0
},
/* CHANTYPE */
{
DW_TAG_typedef
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
0
,
0
},
/* FUNCTYPE */
{
DW_TAG_typedef
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
0
,
0
},
/* IFACETYPE */
{
DW_TAG_interface_type
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
0
,
0
},
/* MAPTYPE */
{
DW_TAG_typedef
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
0
,
0
},
/* PTRTYPE */
{
DW_TAG_pointer_type
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_type
,
DW_FORM_ref_addr
,
0
,
0
},
/* SLICETYPE */
// Children are data, len and cap of runtime::struct Slice.
{
DW_TAG_structure_type
,
DW_CHILDREN_yes
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_byte_size
,
DW_FORM_udata
,
0
,
0
},
/* STRINGTYPE */
// Children are str and len of runtime::struct String.
{
DW_TAG_structure_type
,
DW_CHILDREN_yes
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_byte_size
,
DW_FORM_udata
,
0
,
0
},
/* STRUCTTYPE */
{
DW_TAG_structure_type
,
DW_CHILDREN_yes
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_byte_size
,
DW_FORM_udata
,
0
,
0
},
/* TYPEDECL */
{
DW_TAG_typedef
,
DW_CHILDREN_no
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_type
,
DW_FORM_ref_addr
,
0
,
0
0
,
0
},
},
};
};
...
@@ -154,8 +312,8 @@ writeabbrev(void)
...
@@ -154,8 +312,8 @@ writeabbrev(void)
uleb128put
(
i
);
uleb128put
(
i
);
uleb128put
(
abbrevs
[
i
].
tag
);
uleb128put
(
abbrevs
[
i
].
tag
);
cput
(
abbrevs
[
i
].
children
);
cput
(
abbrevs
[
i
].
children
);
// 0 is not a valid attr or form,
so we can treat this a
s
// 0 is not a valid attr or form,
and DWAbbrev.attr i
s
// a string
//
0-terminated, so we can treat it as
a string
n
=
strlen
((
char
*
)
abbrevs
[
i
].
attr
)
/
2
;
n
=
strlen
((
char
*
)
abbrevs
[
i
].
attr
)
/
2
;
strnput
((
char
*
)
abbrevs
[
i
].
attr
,
strnput
((
char
*
)
abbrevs
[
i
].
attr
,
(
n
+
1
)
*
sizeof
(
DWAttrForm
));
(
n
+
1
)
*
sizeof
(
DWAttrForm
));
...
@@ -165,12 +323,29 @@ writeabbrev(void)
...
@@ -165,12 +323,29 @@ writeabbrev(void)
}
}
/*
/*
* Debugging Information Entries and their attributes
* Debugging Information Entries and their attributes
.
*/
*/
enum
{
HASHSIZE
=
107
};
static
uint32
hashstr
(
char
*
s
)
{
uint32
h
;
h
=
0
;
while
(
*
s
)
h
=
h
+
h
+
h
+
*
s
++
;
return
h
%
HASHSIZE
;
}
// For DW_CLS_string and _block, value should contain the length, and
// For DW_CLS_string and _block, value should contain the length, and
// data the data, for all others, value is the whole thing and data is
// data the data, for _reference, value is 0 and data is a DWDie* to
// null.
// the referenced instance, for all others, value is the whole thing
// and data is null.
typedef
struct
DWAttr
DWAttr
;
typedef
struct
DWAttr
DWAttr
;
struct
DWAttr
{
struct
DWAttr
{
...
@@ -187,21 +362,20 @@ struct DWDie {
...
@@ -187,21 +362,20 @@ struct DWDie {
DWDie
*
link
;
DWDie
*
link
;
DWDie
*
child
;
DWDie
*
child
;
DWAttr
*
attr
;
DWAttr
*
attr
;
// offset into .debug_info section, i.e relative to
// infoo. only valid after call to putdie()
vlong
offs
;
DWDie
**
hash
;
// optional index of children by name, enabled by mkindex()
DWDie
*
hlink
;
// bucket chain in parent's index
};
};
// top level compilation unit DIE's
/*
static
DWDie
*
dwinfo
;
* Root DIEs for compilation units, types and global variables.
*/
static
DWDie
*
newdie
(
DWDie
*
link
,
int
abbrev
)
{
DWDie
*
die
;
die
=
mal
(
sizeof
*
die
);
static
DWDie
dwroot
;
die
->
abbrev
=
abbrev
;
static
DWDie
dwtypes
;
die
->
link
=
link
;
static
DWDie
dwglobals
;
return
die
;
}
static
DWAttr
*
static
DWAttr
*
newattr
(
DWDie
*
die
,
uint8
attr
,
int
cls
,
vlong
value
,
char
*
data
)
newattr
(
DWDie
*
die
,
uint8
attr
,
int
cls
,
vlong
value
,
char
*
data
)
...
@@ -218,6 +392,109 @@ newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data)
...
@@ -218,6 +392,109 @@ newattr(DWDie *die, uint8 attr, int cls, vlong value, char *data)
return
a
;
return
a
;
}
}
// Each DIE (except the root ones) has at least 1 attribute: its
// name. getattr moves the desired one to the front so
// frequently searched ones are found faster.
static
DWAttr
*
getattr
(
DWDie
*
die
,
uint8
attr
)
{
DWAttr
*
a
,
*
b
;
if
(
die
->
attr
->
atr
==
attr
)
return
die
->
attr
;
a
=
die
->
attr
;
b
=
a
->
link
;
while
(
b
!=
nil
)
{
if
(
b
->
atr
==
attr
)
{
a
->
link
=
b
->
link
;
b
->
link
=
die
->
attr
;
die
->
attr
=
b
;
return
b
;
}
a
=
b
;
b
=
b
->
link
;
}
return
nil
;
}
// Every DIE has at least a DW_AT_name attribute (but it will only be
// written out if it is listed in the abbrev). If its parent is
// keeping an index, the new DIE will be inserted there.
static
DWDie
*
newdie
(
DWDie
*
parent
,
int
abbrev
,
char
*
name
)
{
DWDie
*
die
;
int
h
;
die
=
mal
(
sizeof
*
die
);
die
->
abbrev
=
abbrev
;
die
->
link
=
parent
->
child
;
parent
->
child
=
die
;
newattr
(
die
,
DW_AT_name
,
DW_CLS_STRING
,
strlen
(
name
),
name
);
if
(
parent
->
hash
)
{
h
=
hashstr
(
name
);
die
->
hlink
=
parent
->
hash
[
h
];
parent
->
hash
[
h
]
=
die
;
}
return
die
;
}
static
void
mkindex
(
DWDie
*
die
)
{
die
->
hash
=
mal
(
HASHSIZE
*
sizeof
(
DWDie
*
));
}
static
DWDie
*
find
(
DWDie
*
die
,
char
*
name
)
{
DWDie
*
a
,
*
b
;
int
h
;
if
(
die
->
hash
==
nil
)
{
diag
(
"lookup of %s in non-indexed DIE"
,
name
);
errorexit
();
}
h
=
hashstr
(
name
);
a
=
die
->
hash
[
h
];
if
(
a
==
nil
)
return
nil
;
// AT_name always exists.
if
(
strcmp
(
name
,
getattr
(
a
,
DW_AT_name
)
->
data
)
==
0
)
return
a
;
// Move found ones to head of the list.
b
=
a
->
hlink
;
while
(
b
!=
nil
)
{
if
(
strcmp
(
name
,
getattr
(
b
,
DW_AT_name
)
->
data
)
==
0
)
{
a
->
hlink
=
b
->
hlink
;
b
->
hlink
=
die
->
hash
[
h
];
die
->
hash
[
h
]
=
b
;
return
b
;
}
a
=
b
;
b
=
b
->
hlink
;
}
return
nil
;
}
static
DWAttr
*
newrefattr
(
DWDie
*
die
,
uint8
attr
,
DWDie
*
ref
)
{
if
(
ref
==
nil
)
return
nil
;
return
newattr
(
die
,
attr
,
DW_CLS_REFERENCE
,
0
,
(
char
*
)
ref
);
}
static
int
fwdcount
;
static
void
static
void
putattr
(
int
form
,
int
cls
,
vlong
value
,
char
*
data
)
putattr
(
int
form
,
int
cls
,
vlong
value
,
char
*
data
)
{
{
...
@@ -285,13 +562,24 @@ putattr(int form, int cls, vlong value, char *data)
...
@@ -285,13 +562,24 @@ putattr(int form, int cls, vlong value, char *data)
cput
(
value
?
1
:
0
);
cput
(
value
?
1
:
0
);
break
;
break
;
case
DW_FORM_strp
:
// string
case
DW_FORM_ref_addr
:
// reference to a DIE in the .info section
case
DW_FORM_ref_addr
:
// reference
if
(
data
==
nil
)
{
case
DW_FORM_ref1
:
// reference
diag
(
"null dwarf reference"
);
LPUT
(
0
);
// invalid dwarf, gdb will complain.
}
else
{
if
(((
DWDie
*
)
data
)
->
offs
==
0
)
fwdcount
++
;
LPUT
(((
DWDie
*
)
data
)
->
offs
);
}
break
;
case
DW_FORM_ref1
:
// reference within the compilation unit
case
DW_FORM_ref2
:
// reference
case
DW_FORM_ref2
:
// reference
case
DW_FORM_ref4
:
// reference
case
DW_FORM_ref4
:
// reference
case
DW_FORM_ref8
:
// reference
case
DW_FORM_ref8
:
// reference
case
DW_FORM_ref_udata
:
// reference
case
DW_FORM_ref_udata
:
// reference
case
DW_FORM_strp
:
// string
case
DW_FORM_indirect
:
// (see Section 7.5.3)
case
DW_FORM_indirect
:
// (see Section 7.5.3)
default:
default:
diag
(
"Unsupported atribute form %d / class %d"
,
form
,
cls
);
diag
(
"Unsupported atribute form %d / class %d"
,
form
,
cls
);
...
@@ -330,6 +618,7 @@ putdies(DWDie* die)
...
@@ -330,6 +618,7 @@ putdies(DWDie* die)
static
void
static
void
putdie
(
DWDie
*
die
)
putdie
(
DWDie
*
die
)
{
{
die
->
offs
=
cpos
()
-
infoo
;
uleb128put
(
die
->
abbrev
);
uleb128put
(
die
->
abbrev
);
putattrs
(
die
->
abbrev
,
die
->
attr
);
putattrs
(
die
->
abbrev
,
die
->
attr
);
if
(
abbrevs
[
die
->
abbrev
].
children
)
{
if
(
abbrevs
[
die
->
abbrev
].
children
)
{
...
@@ -344,8 +633,8 @@ reverselist(DWDie** list)
...
@@ -344,8 +633,8 @@ reverselist(DWDie** list)
DWDie
*
curr
,
*
prev
;
DWDie
*
curr
,
*
prev
;
curr
=
*
list
;
curr
=
*
list
;
prev
=
0
;
prev
=
nil
;
while
(
curr
)
{
while
(
curr
!=
nil
)
{
DWDie
*
next
=
curr
->
link
;
DWDie
*
next
=
curr
->
link
;
curr
->
link
=
prev
;
curr
->
link
=
prev
;
prev
=
curr
;
prev
=
curr
;
...
@@ -360,11 +649,397 @@ reversetree(DWDie** list)
...
@@ -360,11 +649,397 @@ reversetree(DWDie** list)
DWDie
*
die
;
DWDie
*
die
;
reverselist
(
list
);
reverselist
(
list
);
if
(
*
list
!=
nil
&&
abbrevs
[(
*
list
)
->
abbrev
].
children
)
for
(
die
=
*
list
;
die
!=
nil
;
die
=
die
->
link
)
for
(
die
=
*
list
;
die
!=
nil
;
die
=
die
->
link
)
if
(
abbrevs
[
die
->
abbrev
].
children
)
reversetree
(
&
die
->
child
);
reversetree
(
&
die
->
child
);
}
}
static
void
newmemberoffsetattr
(
DWDie
*
die
,
int32
offs
)
{
char
block
[
10
];
int
i
;
i
=
0
;
if
(
offs
!=
0
)
{
block
[
i
++
]
=
DW_OP_consts
;
i
+=
sleb128enc
(
offs
,
block
+
i
);
block
[
i
++
]
=
DW_OP_plus
;
}
newattr
(
die
,
DW_AT_data_member_location
,
DW_CLS_BLOCK
,
i
,
mal
(
i
));
memmove
(
die
->
attr
->
data
,
block
,
i
);
}
// Decoding the type.* symbols. This has to be in sync with
// ../../pkg/runtime/type.go, or more specificaly, with what
// ../gc/reflect.c stuffs in these.
enum
{
KindBool
=
1
,
KindInt
,
KindInt8
,
KindInt16
,
KindInt32
,
KindInt64
,
KindUint
,
KindUint8
,
KindUint16
,
KindUint32
,
KindUint64
,
KindUintptr
,
KindFloat
,
KindFloat32
,
KindFloat64
,
KindComplex
,
KindComplex64
,
KindComplex128
,
KindArray
,
KindChan
,
KindFunc
,
KindInterface
,
KindMap
,
KindPtr
,
KindSlice
,
KindString
,
KindStruct
,
KindUnsafePointer
,
KindNoPointers
=
1
<<
7
,
};
static
Sym
*
decode_reloc
(
Sym
*
s
,
int32
off
)
{
int
i
;
for
(
i
=
0
;
i
<
s
->
nr
;
i
++
)
if
(
s
->
r
[
i
].
off
==
off
)
return
s
->
r
[
i
].
sym
;
return
nil
;
}
static
uvlong
decode_inuxi
(
uchar
*
p
,
int
sz
)
{
uvlong
r
;
uchar
*
inuxi
;
int
i
;
r
=
0
;
inuxi
=
nil
;
switch
(
sz
)
{
case
2
:
inuxi
=
inuxi2
;
break
;
case
4
:
inuxi
=
inuxi4
;
break
;
case
8
:
inuxi
=
inuxi8
;
break
;
default:
diag
(
"decode inuxi %d"
,
sz
);
errorexit
();
}
for
(
i
=
0
;
i
<
sz
;
i
++
)
r
+=
p
[
i
]
<<
(
8
*
inuxi
[
i
]);
return
r
;
}
// Type.commonType.kind
static
uint8
decodetype_kind
(
Sym
*
s
)
{
return
s
->
p
[
3
*
PtrSize
+
7
]
&
~
KindNoPointers
;
// 0x13 / 0x1f
}
// Type.commonType.size
static
vlong
decodetype_size
(
Sym
*
s
)
{
return
decode_inuxi
(
s
->
p
+
2
*
PtrSize
,
PtrSize
);
// 0x8 / 0x10
}
// Type.ArrayType.elem
static
Sym
*
decodetype_arrayelem
(
Sym
*
s
)
{
return
decode_reloc
(
s
,
5
*
PtrSize
+
8
);
// 0x1c / 0x30
}
// Type.PtrType.elem
static
Sym
*
decodetype_ptrelem
(
Sym
*
s
)
{
return
decode_reloc
(
s
,
5
*
PtrSize
+
8
);
// 0x1c / 0x30
}
// Type.StructType.fields.Slice::len
static
int
decodetype_structfieldcount
(
Sym
*
s
)
{
return
decode_inuxi
(
s
->
p
+
6
*
PtrSize
+
8
,
4
);
// 0x20 / 0x38
}
// Type.StructType.fields[]-> name, typ and offset. sizeof(structField) = 5*PtrSize
static
uchar
*
decodetype_structfieldname
(
Sym
*
s
,
int
i
)
{
Sym
*
p
;
p
=
decode_reloc
(
s
,
6
*
PtrSize
+
0x10
+
i
*
5
*
PtrSize
);
// go.string."foo" 0x28 / 0x40
if
(
p
==
nil
)
// embedded structs have a nil name.
return
nil
;
p
=
decode_reloc
(
p
,
0
);
// string."foo"
if
(
p
==
nil
)
// shouldn't happen.
return
nil
;
return
p
->
p
;
// the c-string
}
static
Sym
*
decodetype_structfieldtype
(
Sym
*
s
,
int
i
)
{
return
decode_reloc
(
s
,
8
*
PtrSize
+
0x10
+
i
*
5
*
PtrSize
);
// 0x30 / 0x50
}
static
vlong
decodetype_structfieldoffs
(
Sym
*
s
,
int
i
)
{
return
decode_inuxi
(
s
->
p
+
10
*
PtrSize
+
0x10
+
i
*
5
*
PtrSize
,
4
);
// 0x38 / 0x60
}
// Define gotype, for composite ones recurse into constituents.
static
DWDie
*
defgotype
(
Sym
*
gotype
)
{
DWDie
*
die
,
*
fld
,
*
elem
,
*
ptrelem
;
Sym
*
s
;
char
*
name
,
*
ptrname
,
*
f
;
uint8
kind
;
vlong
bytesize
;
int
i
,
nfields
;
if
(
gotype
==
nil
)
return
find
(
&
dwtypes
,
"<unspecified>"
);
// must be defined before
if
(
strncmp
(
"type."
,
gotype
->
name
,
5
)
!=
0
)
{
diag
(
"Type name doesn't start with
\"
.type
\"
: %s"
,
gotype
->
name
);
return
find
(
&
dwtypes
,
"<unspecified>"
);
}
name
=
gotype
->
name
+
5
;
// Altenatively decode from Type.string
die
=
find
(
&
dwtypes
,
name
);
if
(
die
!=
nil
)
return
die
;
if
(
0
&&
debug
[
'v'
]
>
2
)
{
print
(
"new type: %s @0x%08x [%d]"
,
gotype
->
name
,
gotype
->
value
,
gotype
->
size
);
for
(
i
=
0
;
i
<
gotype
->
size
;
++
i
)
{
if
(
!
(
i
%
8
))
print
(
"
\n\t
%04x "
,
i
);
print
(
"%02x "
,
gotype
->
p
[
i
]);
}
print
(
"
\n
"
);
for
(
i
=
0
;
i
<
gotype
->
nr
;
++
i
)
{
print
(
"
\t
%02x %d %d %lld %s
\n
"
,
gotype
->
r
[
i
].
off
,
gotype
->
r
[
i
].
siz
,
gotype
->
r
[
i
].
type
,
gotype
->
r
[
i
].
add
,
gotype
->
r
[
i
].
sym
->
name
);
}
}
kind
=
decodetype_kind
(
gotype
);
bytesize
=
decodetype_size
(
gotype
);
switch
(
kind
)
{
case
KindBool
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_BASETYPE
,
name
);
newattr
(
die
,
DW_AT_encoding
,
DW_CLS_CONSTANT
,
DW_ATE_boolean
,
0
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
break
;
case
KindInt
:
case
KindInt8
:
case
KindInt16
:
case
KindInt32
:
case
KindInt64
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_BASETYPE
,
name
);
newattr
(
die
,
DW_AT_encoding
,
DW_CLS_CONSTANT
,
DW_ATE_signed
,
0
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
break
;
case
KindUint
:
case
KindUint8
:
case
KindUint16
:
case
KindUint32
:
case
KindUint64
:
case
KindUintptr
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_BASETYPE
,
name
);
newattr
(
die
,
DW_AT_encoding
,
DW_CLS_CONSTANT
,
DW_ATE_unsigned
,
0
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
break
;
case
KindFloat
:
case
KindFloat32
:
case
KindFloat64
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_BASETYPE
,
name
);
newattr
(
die
,
DW_AT_encoding
,
DW_CLS_CONSTANT
,
DW_ATE_float
,
0
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
break
;
case
KindComplex
:
case
KindComplex64
:
case
KindComplex128
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_BASETYPE
,
name
);
newattr
(
die
,
DW_AT_encoding
,
DW_CLS_CONSTANT
,
DW_ATE_complex_float
,
0
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
break
;
case
KindArray
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_ARRAYTYPE
,
name
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
s
=
decodetype_arrayelem
(
gotype
);
newrefattr
(
die
,
DW_AT_type
,
defgotype
(
s
));
break
;
case
KindChan
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_CHANTYPE
,
name
);
// TODO: describe ../../pkg/runtime/chan.c::struct Hchan
break
;
case
KindFunc
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_FUNCTYPE
,
name
);
break
;
case
KindInterface
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_IFACETYPE
,
name
);
break
;
case
KindMap
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_MAPTYPE
,
name
);
// TODO: describe ../../pkg/runtime/hashmap.c::struct hash
break
;
case
KindPtr
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_PTRTYPE
,
name
);
s
=
decodetype_ptrelem
(
gotype
);
newrefattr
(
die
,
DW_AT_type
,
defgotype
(
s
));
break
;
case
KindSlice
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_SLICETYPE
,
name
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
fld
=
newdie
(
die
,
DW_ABRV_STRUCTFIELD
,
"data"
);
// Synthesize *elemtype if not already exists. Maybe
// this should be named '<*T>' to not stand in the way
// of the real definition of *T.
s
=
decodetype_arrayelem
(
gotype
);
elem
=
defgotype
(
s
);
ptrname
=
strdup
(
s
->
name
+
4
);
// skip "type" but leave the '.'
ptrname
[
0
]
=
'*'
;
// .. to stuff in the '*'
ptrelem
=
find
(
&
dwtypes
,
ptrname
);
if
(
ptrelem
==
nil
)
{
ptrelem
=
newdie
(
&
dwtypes
,
DW_ABRV_PTRTYPE
,
ptrname
);
newrefattr
(
ptrelem
,
DW_AT_type
,
elem
);
}
else
{
free
(
ptrname
);
}
newrefattr
(
fld
,
DW_AT_type
,
ptrelem
);
newmemberoffsetattr
(
fld
,
0
);
fld
=
newdie
(
die
,
DW_ABRV_STRUCTFIELD
,
"len"
);
newrefattr
(
fld
,
DW_AT_type
,
find
(
&
dwtypes
,
"<int32>"
));
newmemberoffsetattr
(
fld
,
PtrSize
);
fld
=
newdie
(
die
,
DW_ABRV_STRUCTFIELD
,
"cap"
);
newrefattr
(
fld
,
DW_AT_type
,
find
(
&
dwtypes
,
"<int32>"
));
newmemberoffsetattr
(
fld
,
PtrSize
+
4
);
break
;
case
KindString
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_STRINGTYPE
,
name
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
fld
=
newdie
(
die
,
DW_ABRV_STRUCTFIELD
,
"str"
);
newrefattr
(
fld
,
DW_AT_type
,
find
(
&
dwtypes
,
"<byte*>"
));
newmemberoffsetattr
(
fld
,
0
);
fld
=
newdie
(
die
,
DW_ABRV_STRUCTFIELD
,
"len"
);
newrefattr
(
fld
,
DW_AT_type
,
find
(
&
dwtypes
,
"<int32>"
));
newmemberoffsetattr
(
fld
,
PtrSize
);
break
;
case
KindStruct
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_STRUCTTYPE
,
name
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
bytesize
,
0
);
nfields
=
decodetype_structfieldcount
(
gotype
);
for
(
i
=
0
;
i
<
nfields
;
++
i
)
{
f
=
decodetype_structfieldname
(
gotype
,
i
);
s
=
decodetype_structfieldtype
(
gotype
,
i
);
if
(
f
==
nil
)
f
=
s
->
name
+
5
;
// skip "type."
fld
=
newdie
(
die
,
DW_ABRV_STRUCTFIELD
,
f
);
newrefattr
(
fld
,
DW_AT_type
,
defgotype
(
s
));
newmemberoffsetattr
(
fld
,
decodetype_structfieldoffs
(
gotype
,
i
));
}
break
;
case
KindUnsafePointer
:
die
=
newdie
(
&
dwtypes
,
DW_ABRV_PTRTYPE
,
name
);
newrefattr
(
die
,
DW_AT_type
,
find
(
&
dwtypes
,
"void"
));
break
;
default:
diag
(
"definition of unknown kind %d: %s"
,
kind
,
gotype
->
name
);
die
=
newdie
(
&
dwtypes
,
DW_ABRV_TYPEDECL
,
name
);
newrefattr
(
die
,
DW_AT_type
,
find
(
&
dwtypes
,
"<unspecified>"
));
}
return
die
;
}
// For use with pass.c::genasmsym
static
void
defdwsymb
(
Sym
*
sym
,
char
*
s
,
int
t
,
vlong
v
,
vlong
size
,
int
ver
,
Sym
*
gotype
)
{
DWDie
*
dv
,
*
dt
;
if
(
gotype
==
nil
)
{
return
;
}
dv
=
nil
;
switch
(
t
)
{
default:
return
;
case
'D'
:
case
'B'
:
dv
=
newdie
(
&
dwglobals
,
DW_ABRV_VARIABLE
,
s
);
newattr
(
dv
,
DW_AT_location
,
DW_CLS_ADDRESS
,
v
,
0
);
if
(
ver
==
0
)
newattr
(
dv
,
DW_AT_external
,
DW_CLS_FLAG
,
1
,
0
);
// fallthrough
case
'a'
:
case
'p'
:
dt
=
defgotype
(
gotype
);
}
if
(
dv
!=
nil
)
newrefattr
(
dv
,
DW_AT_type
,
dt
);
}
// TODO(lvd) For now, just append them all to the first compilation
// unit (that should be main), in the future distribute them to the
// appropriate compilation units.
static
void
movetomodule
(
DWDie
*
parent
)
{
DWDie
*
die
;
for
(
die
=
dwroot
.
child
->
child
;
die
->
link
!=
nil
;
die
=
die
->
link
)
/* nix */
;
die
->
link
=
parent
->
child
;
}
/*
/*
* Filename fragments for the line history stack.
* Filename fragments for the line history stack.
*/
*/
...
@@ -511,11 +1186,14 @@ checknesting(void)
...
@@ -511,11 +1186,14 @@ checknesting(void)
}
}
}
}
/* find z and Z entries in the Auto list (of a Prog), and reset the history stack */
/*
static
char
*
* Return false if the a->link chain contains no history, otherwise
* returns true and finds z and Z entries in the Auto list (of a
* Prog), and resets the history stack
*/
static
int
inithist
(
Auto
*
a
)
inithist
(
Auto
*
a
)
{
{
char
*
unitname
;
Linehist
*
lh
;
Linehist
*
lh
;
for
(;
a
;
a
=
a
->
link
)
for
(;
a
;
a
=
a
->
link
)
...
@@ -531,8 +1209,6 @@ inithist(Auto *a)
...
@@ -531,8 +1209,6 @@ inithist(Auto *a)
return
0
;
return
0
;
}
}
unitname
=
decodez
(
a
->
asym
->
name
);
// Clear the history.
// Clear the history.
clearhistfile
();
clearhistfile
();
includetop
=
0
;
includetop
=
0
;
...
@@ -558,7 +1234,6 @@ inithist(Auto *a)
...
@@ -558,7 +1234,6 @@ inithist(Auto *a)
checknesting
();
checknesting
();
includestack
[
includetop
].
file
=
f
;
includestack
[
includetop
].
file
=
f
;
includestack
[
includetop
].
line
=
1
;
includestack
[
includetop
].
line
=
1
;
}
}
absline
=
a
->
aoffset
;
absline
=
a
->
aoffset
;
}
else
if
(
a
->
type
==
D_FILE1
)
{
// 'Z'
}
else
if
(
a
->
type
==
D_FILE1
)
{
// 'Z'
...
@@ -580,7 +1255,7 @@ inithist(Auto *a)
...
@@ -580,7 +1255,7 @@ inithist(Auto *a)
linehist
->
file
=
includestack
[
includetop
].
file
;
linehist
->
file
=
includestack
[
includetop
].
file
;
linehist
->
line
=
includestack
[
includetop
].
line
;
linehist
->
line
=
includestack
[
includetop
].
line
;
}
}
return
unitname
;
return
1
;
}
}
static
Linehist
*
static
Linehist
*
...
@@ -635,6 +1310,23 @@ putpclcdelta(vlong delta_pc, vlong delta_lc)
...
@@ -635,6 +1310,23 @@ putpclcdelta(vlong delta_pc, vlong delta_lc)
cput
(
DW_LNS_copy
);
cput
(
DW_LNS_copy
);
}
}
static
void
newcfaoffsetattr
(
DWDie
*
die
,
int32
offs
)
{
char
block
[
10
];
int
i
;
i
=
0
;
block
[
i
++
]
=
DW_OP_call_frame_cfa
;
if
(
offs
!=
0
)
{
block
[
i
++
]
=
DW_OP_consts
;
i
+=
sleb128enc
(
offs
,
block
+
i
);
block
[
i
++
]
=
DW_OP_plus
;
}
newattr
(
die
,
DW_AT_location
,
DW_CLS_BLOCK
,
i
,
mal
(
i
));
memmove
(
die
->
attr
->
data
,
block
,
i
);
}
/*
/*
* Walk prog table, emit line program and build DIE tree.
* Walk prog table, emit line program and build DIE tree.
...
@@ -642,7 +1334,7 @@ putpclcdelta(vlong delta_pc, vlong delta_lc)
...
@@ -642,7 +1334,7 @@ putpclcdelta(vlong delta_pc, vlong delta_lc)
// flush previous compilation unit.
// flush previous compilation unit.
static
void
static
void
flushunit
(
vlong
pc
,
vlong
unitstart
)
flushunit
(
DWDie
*
dwinfo
,
vlong
pc
,
vlong
unitstart
)
{
{
vlong
here
;
vlong
here
;
...
@@ -669,12 +1361,13 @@ writelines(void)
...
@@ -669,12 +1361,13 @@ writelines(void)
{
{
Prog
*
q
;
Prog
*
q
;
Sym
*
s
;
Sym
*
s
;
char
*
unitname
;
Auto
*
a
;
vlong
unitstart
;
vlong
unitstart
;
vlong
pc
,
epc
,
lc
,
llc
,
lline
;
vlong
pc
,
epc
,
lc
,
llc
,
lline
;
int
currfile
;
int
currfile
;
int
i
;
int
i
,
lang
;
Linehist
*
lh
;
Linehist
*
lh
;
DWDie
*
dwinfo
,
*
dwfunc
,
*
dwvar
;
unitstart
=
-
1
;
unitstart
=
-
1
;
epc
=
pc
=
0
;
epc
=
pc
=
0
;
...
@@ -682,32 +1375,39 @@ writelines(void)
...
@@ -682,32 +1375,39 @@ writelines(void)
llc
=
1
;
llc
=
1
;
currfile
=
-
1
;
currfile
=
-
1
;
lineo
=
cpos
();
lineo
=
cpos
();
dwinfo
=
nil
;
for
(
cursym
=
textp
;
cursym
!=
nil
;
cursym
=
cursym
->
next
)
{
for
(
cursym
=
textp
;
cursym
!=
nil
;
cursym
=
cursym
->
next
)
{
s
=
cursym
;
s
=
cursym
;
// Look for history stack. If we find one,
// Look for history stack. If we find one,
// we're entering a new compilation unit
// we're entering a new compilation unit
if
((
unitname
=
inithist
(
s
->
autom
))
!=
0
)
{
flushunit
(
epc
,
unitstart
);
if
(
inithist
(
s
->
autom
))
{
flushunit
(
dwinfo
,
epc
,
unitstart
);
unitstart
=
cpos
();
unitstart
=
cpos
();
if
(
debug
[
'v'
]
>
1
)
{
if
(
debug
[
'v'
]
>
1
)
{
print
(
"dwarf writelines found %s
\n
"
,
unitname
);
print
(
"dwarf writelines found %s
\n
"
,
histfile
[
1
]
);
Linehist
*
lh
;
Linehist
*
lh
;
for
(
lh
=
linehist
;
lh
;
lh
=
lh
->
link
)
for
(
lh
=
linehist
;
lh
;
lh
=
lh
->
link
)
print
(
"
\t
%8lld: [%4lld]%s
\n
"
,
print
(
"
\t
%8lld: [%4lld]%s
\n
"
,
lh
->
absline
,
lh
->
line
,
histfile
[
lh
->
file
]);
lh
->
absline
,
lh
->
line
,
histfile
[
lh
->
file
]);
}
}
dwinfo
=
newdie
(
dwinfo
,
DW_ABRV_COMPUNIT
);
newattr
(
dwinfo
,
DW_AT_name
,
DW_CLS_STRING
,
strlen
(
unitname
),
unitname
);
lang
=
guesslang
(
histfile
[
1
]);
newattr
(
dwinfo
,
DW_AT_language
,
DW_CLS_CONSTANT
,
guesslang
(
unitname
),
0
);
dwinfo
=
newdie
(
&
dwroot
,
DW_ABRV_COMPUNIT
,
strdup
(
histfile
[
1
]));
newattr
(
dwinfo
,
DW_AT_language
,
DW_CLS_CONSTANT
,
lang
,
0
);
newattr
(
dwinfo
,
DW_AT_stmt_list
,
DW_CLS_PTR
,
unitstart
-
lineo
,
0
);
newattr
(
dwinfo
,
DW_AT_stmt_list
,
DW_CLS_PTR
,
unitstart
-
lineo
,
0
);
newattr
(
dwinfo
,
DW_AT_low_pc
,
DW_CLS_ADDRESS
,
s
->
text
->
pc
,
0
);
newattr
(
dwinfo
,
DW_AT_low_pc
,
DW_CLS_ADDRESS
,
s
->
text
->
pc
,
0
);
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
// Fields marked with (*) must be changed for 64-bit dwarf
LPUT
(
0
);
// unit_length (*), will be filled in later.
LPUT
(
0
);
// unit_length (*), will be filled in later.
WPUT
(
3
);
// version
WPUT
(
3
);
// dwarf version (appendix F)
LPUT
(
11
);
// header_length (*)
LPUT
(
11
);
// header_length (*), starting here.
cput
(
1
);
// minimum_instruction_length
cput
(
1
);
// minimum_instruction_length
cput
(
1
);
// default_is_stmt
cput
(
1
);
// default_is_stmt
cput
(
LINE_BASE
);
// line_base
cput
(
LINE_BASE
);
// line_base
...
@@ -719,6 +1419,8 @@ writelines(void)
...
@@ -719,6 +1419,8 @@ writelines(void)
cput
(
1
);
// standard_opcode_lengths[4]
cput
(
1
);
// standard_opcode_lengths[4]
cput
(
0
);
// include_directories (empty)
cput
(
0
);
// include_directories (empty)
cput
(
0
);
// file_names (empty) (emitted by DW_LNE's below)
cput
(
0
);
// file_names (empty) (emitted by DW_LNE's below)
// header_length ends here.
for
(
i
=
1
;
i
<
histfilesize
;
i
++
)
{
for
(
i
=
1
;
i
<
histfilesize
;
i
++
)
{
cput
(
0
);
// start extended opcode
cput
(
0
);
// start extended opcode
uleb128put
(
1
+
strlen
(
histfile
[
i
])
+
4
);
uleb128put
(
1
+
strlen
(
histfile
[
i
])
+
4
);
...
@@ -745,11 +1447,12 @@ writelines(void)
...
@@ -745,11 +1447,12 @@ writelines(void)
continue
;
continue
;
}
}
dwinfo
->
child
=
newdie
(
dwinfo
->
child
,
DW_ABRV_FUNCTION
);
dwfunc
=
newdie
(
dwinfo
,
DW_ABRV_FUNCTION
,
s
->
name
);
newattr
(
dwinfo
->
child
,
DW_AT_name
,
DW_CLS_STRING
,
strlen
(
s
->
name
),
s
->
name
);
newattr
(
dwfunc
,
DW_AT_low_pc
,
DW_CLS_ADDRESS
,
s
->
value
,
0
);
newattr
(
dwinfo
->
child
,
DW_AT_low_pc
,
DW_CLS_ADDRESS
,
s
->
value
,
0
);
epc
=
s
->
value
+
s
->
size
;
epc
=
s
->
value
+
s
->
size
;
newattr
(
dwinfo
->
child
,
DW_AT_high_pc
,
DW_CLS_ADDRESS
,
epc
,
0
);
newattr
(
dwfunc
,
DW_AT_high_pc
,
DW_CLS_ADDRESS
,
epc
,
0
);
if
(
s
->
version
==
0
)
newattr
(
dwfunc
,
DW_AT_external
,
DW_CLS_FLAG
,
1
,
0
);
for
(
q
=
s
->
text
;
q
!=
P
;
q
=
q
->
link
)
{
for
(
q
=
s
->
text
;
q
!=
P
;
q
=
q
->
link
)
{
lh
=
searchhist
(
q
->
line
);
lh
=
searchhist
(
q
->
line
);
...
@@ -757,8 +1460,9 @@ writelines(void)
...
@@ -757,8 +1460,9 @@ writelines(void)
diag
(
"corrupt history or bad absolute line: %P"
,
q
);
diag
(
"corrupt history or bad absolute line: %P"
,
q
);
continue
;
continue
;
}
}
if
(
lh
->
file
<
1
)
{
// 0 is the past-EOF entry.
if
(
lh
->
file
<
1
)
{
// 0 is the past-EOF entry.
//
diag("instruction with line number past EOF in %s: %P", unitname
, q);
//
diag("instruction with line number past EOF in %s: %P", histfile[1]
, q);
continue
;
continue
;
}
}
...
@@ -778,9 +1482,24 @@ writelines(void)
...
@@ -778,9 +1482,24 @@ writelines(void)
lc
=
q
->
line
;
lc
=
q
->
line
;
llc
=
lline
;
llc
=
lline
;
}
}
for
(
a
=
s
->
autom
;
a
;
a
=
a
->
link
)
{
switch
(
a
->
type
)
{
case
D_AUTO
:
dwvar
=
newdie
(
dwfunc
,
DW_ABRV_AUTO
,
a
->
asym
->
name
);
break
;
case
D_PARAM
:
dwvar
=
newdie
(
dwfunc
,
DW_ABRV_PARAM
,
a
->
asym
->
name
);
break
;
default:
continue
;
}
newcfaoffsetattr
(
dwvar
,
a
->
aoffset
);
newrefattr
(
dwvar
,
DW_AT_type
,
defgotype
(
a
->
gotype
));
}
}
}
flushunit
(
epc
,
unitstart
);
flushunit
(
dwinfo
,
epc
,
unitstart
);
linesize
=
cpos
()
-
lineo
;
linesize
=
cpos
()
-
lineo
;
}
}
...
@@ -824,20 +1543,20 @@ writeframes(void)
...
@@ -824,20 +1543,20 @@ writeframes(void)
frameo
=
cpos
();
frameo
=
cpos
();
// Emit the CIE, Section 6.4.1
// Emit the CIE, Section 6.4.1
LPUT
(
CIERESERVE
);
// initial length, must be multiple of PtrSize
LPUT
(
CIERESERVE
);
// initial length, must be multiple of PtrSize
LPUT
(
0xffffffff
);
// cid.
LPUT
(
0xffffffff
);
// cid.
cput
(
3
);
// dwarf version
cput
(
3
);
// dwarf version (appendix F)
cput
(
0
);
// augmentation ""
cput
(
0
);
// augmentation ""
uleb128put
(
1
);
// code_alignment_factor
uleb128put
(
1
);
// code_alignment_factor
sleb128put
(
DATAALIGNMENTFACTOR
);
// guess
sleb128put
(
DATAALIGNMENTFACTOR
);
// guess
uleb128put
(
FAKERETURNCOLUMN
);
// return_address_register
uleb128put
(
FAKERETURNCOLUMN
);
// return_address_register
cput
(
DW_CFA_def_cfa
);
cput
(
DW_CFA_def_cfa
);
uleb128put
(
DWARFREGSP
);
// register SP (**ABI-dependent, defined in l.h)
uleb128put
(
DWARFREGSP
);
// register SP (**ABI-dependent, defined in l.h)
uleb128put
(
PtrSize
);
// offset
uleb128put
(
PtrSize
);
// offset
cput
(
DW_CFA_offset
+
FAKERETURNCOLUMN
);
// return address
cput
(
DW_CFA_offset
+
FAKERETURNCOLUMN
);
// return address
uleb128put
(
-
PtrSize
/
DATAALIGNMENTFACTOR
);
// at cfa - x*4
uleb128put
(
-
PtrSize
/
DATAALIGNMENTFACTOR
);
// at cfa - x*4
// 4 is to exclude the length field.
// 4 is to exclude the length field.
pad
=
CIERESERVE
+
frameo
+
4
-
cpos
();
pad
=
CIERESERVE
+
frameo
+
4
-
cpos
();
...
@@ -866,7 +1585,6 @@ writeframes(void)
...
@@ -866,7 +1585,6 @@ writeframes(void)
for
(
q
=
p
;
q
->
link
!=
P
;
q
=
q
->
link
)
{
for
(
q
=
p
;
q
->
link
!=
P
;
q
=
q
->
link
)
{
if
(
q
->
spadj
==
0
)
if
(
q
->
spadj
==
0
)
continue
;
continue
;
cfa
+=
q
->
spadj
;
cfa
+=
q
->
spadj
;
putpccfadelta
(
q
->
link
->
pc
-
pc
,
cfa
);
putpccfadelta
(
q
->
link
->
pc
-
pc
,
cfa
);
pc
=
q
->
link
->
pc
;
pc
=
q
->
link
->
pc
;
...
@@ -896,47 +1614,222 @@ writeframes(void)
...
@@ -896,47 +1614,222 @@ writeframes(void)
/*
/*
* Walk DWarfDebugInfoEntries, and emit .debug_info
* Walk DWarfDebugInfoEntries, and emit .debug_info
*/
*/
enum
{
COMPUNITHEADERSIZE
=
4
+
2
+
4
+
1
};
static
void
static
void
writeinfo
(
void
)
writeinfo
(
void
)
{
{
DWDie
*
compunit
;
DWDie
*
compunit
;
vlong
unitstart
;
vlong
unitstart
,
here
;
reversetree
(
&
dwinfo
)
;
fwdcount
=
0
;
infoo
=
cpos
();
for
(
compunit
=
dwroot
.
child
;
compunit
;
compunit
=
compunit
->
link
)
{
for
(
compunit
=
dwinfo
;
compunit
;
compunit
=
compunit
->
link
)
{
unitstart
=
cpos
();
unitstart
=
cpos
();
// Write .debug_info Compilation Unit Header (sec 7.5.1)
// Write .debug_info Compilation Unit Header (sec 7.5.1)
// Fields marked with (*) must be changed for 64-bit dwarf
// Fields marked with (*) must be changed for 64-bit dwarf
LPUT
(
0
);
// unit_length (*), will be filled in later.
// This must match COMPUNITHEADERSIZE above.
WPUT
(
3
);
// version
LPUT
(
0
);
// unit_length (*), will be filled in later.
LPUT
(
0
);
// debug_abbrev_offset (*)
WPUT
(
3
);
// dwarf version (appendix F)
cput
(
PtrSize
);
// address_size
LPUT
(
0
);
// debug_abbrev_offset (*)
cput
(
PtrSize
);
// address_size
putdie
(
compunit
);
putdie
(
compunit
);
cflush
();
cflush
();
vlong
here
=
cpos
();
here
=
cpos
();
seek
(
cout
,
unitstart
,
0
);
seek
(
cout
,
unitstart
,
0
);
LPUT
(
here
-
unitstart
-
sizeof
(
int32
));
LPUT
(
here
-
unitstart
-
4
);
// exclude the length field.
cflush
();
seek
(
cout
,
here
,
0
);
}
}
/*
* Emit .debug_pubnames/_types. _info must have been written before,
* because we need die->offs and infoo/infosize;
*/
static
int
ispubname
(
DWDie
*
die
)
{
DWAttr
*
a
;
switch
(
die
->
abbrev
)
{
case
DW_ABRV_FUNCTION
:
case
DW_ABRV_VARIABLE
:
a
=
getattr
(
die
,
DW_AT_external
);
return
a
&&
a
->
value
;
}
return
0
;
}
static
int
ispubtype
(
DWDie
*
die
)
{
return
die
->
abbrev
>=
DW_ABRV_NULLTYPE
;
}
static
vlong
writepub
(
int
(
*
ispub
)(
DWDie
*
))
{
DWDie
*
compunit
,
*
die
;
DWAttr
*
dwa
;
vlong
unitstart
,
unitend
,
sectionstart
,
here
;
sectionstart
=
cpos
();
for
(
compunit
=
dwroot
.
child
;
compunit
!=
nil
;
compunit
=
compunit
->
link
)
{
unitstart
=
compunit
->
offs
-
COMPUNITHEADERSIZE
;
if
(
compunit
->
link
!=
nil
)
unitend
=
compunit
->
link
->
offs
-
COMPUNITHEADERSIZE
;
else
unitend
=
infoo
+
infosize
;
// Write .debug_pubnames/types Header (sec 6.1.1)
LPUT
(
0
);
// unit_length (*), will be filled in later.
WPUT
(
2
);
// dwarf version (appendix F)
LPUT
(
unitstart
);
// debug_info_offset (of the Comp unit Header)
LPUT
(
unitend
-
unitstart
);
// debug_info_length
for
(
die
=
compunit
->
child
;
die
!=
nil
;
die
=
die
->
link
)
{
if
(
!
ispub
(
die
))
continue
;
LPUT
(
die
->
offs
-
unitstart
);
dwa
=
getattr
(
die
,
DW_AT_name
);
strnput
(
dwa
->
data
,
dwa
->
value
+
1
);
}
LPUT
(
0
);
cflush
();
here
=
cpos
();
seek
(
cout
,
sectionstart
,
0
);
LPUT
(
here
-
sectionstart
-
4
);
// exclude the length field.
cflush
();
cflush
();
seek
(
cout
,
here
,
0
);
seek
(
cout
,
here
,
0
);
}
}
return
sectionstart
;
}
/*
* emit .debug_aranges. _info must have been written before,
* because we need die->offs of dw_globals.
*/
static
vlong
writearanges
()
{
DWDie
*
compunit
;
DWAttr
*
b
,
*
e
;
int
headersize
;
vlong
sectionstart
;
sectionstart
=
cpos
();
headersize
=
rnd
(
4
+
2
+
4
+
1
+
1
,
PtrSize
);
// don't count unit_length field itself
for
(
compunit
=
dwroot
.
child
;
compunit
!=
nil
;
compunit
=
compunit
->
link
)
{
b
=
getattr
(
compunit
,
DW_AT_low_pc
);
if
(
b
==
nil
)
continue
;
e
=
getattr
(
compunit
,
DW_AT_high_pc
);
if
(
e
==
nil
)
continue
;
// Write .debug_aranges Header + entry (sec 6.1.2)
LPUT
(
headersize
+
4
*
PtrSize
-
4
);
// unit_length (*)
WPUT
(
2
);
// dwarf version (appendix F)
LPUT
(
compunit
->
offs
-
COMPUNITHEADERSIZE
);
// debug_info_offset
cput
(
PtrSize
);
// address_size
cput
(
0
);
// segment_size
strnput
(
""
,
headersize
-
(
4
+
2
+
4
+
1
+
1
));
// align to PtrSize
addrput
(
b
->
value
);
addrput
(
e
->
value
-
b
->
value
);
addrput
(
0
);
addrput
(
0
);
}
cflush
();
cflush
();
infosize
=
cpos
()
-
infoo
;
return
sectionstart
;
}
}
/*
* This is the main entry point for generating dwarf. After emitting
* the mandatory debug_abbrev section, it calls writelines() to set up
* the per-compilation unit part of the DIE tree, while simultaneously
* emitting the debug_line section. When the final tree contains
* forward references, it will write the debug_info section in 2
* passes.
*
*/
void
void
dwarfemitdebugsections
(
void
)
dwarfemitdebugsections
(
void
)
{
{
vlong
infoe
;
DWDie
*
die
;
mkindex
(
&
dwroot
);
mkindex
(
&
dwtypes
);
mkindex
(
&
dwglobals
);
// Some types that must exist to define other ones.
newdie
(
&
dwtypes
,
DW_ABRV_NULLTYPE
,
"<unspecified>"
);
newdie
(
&
dwtypes
,
DW_ABRV_NULLTYPE
,
"void"
);
die
=
newdie
(
&
dwtypes
,
DW_ABRV_PTRTYPE
,
"unsafe.Pointer"
);
newrefattr
(
die
,
DW_AT_type
,
find
(
&
dwtypes
,
"void"
));
die
=
newdie
(
&
dwtypes
,
DW_ABRV_BASETYPE
,
"<int32>"
);
newattr
(
die
,
DW_AT_encoding
,
DW_CLS_CONSTANT
,
DW_ATE_signed
,
0
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
4
,
0
);
die
=
newdie
(
&
dwtypes
,
DW_ABRV_BASETYPE
,
"<byte>"
);
newattr
(
die
,
DW_AT_encoding
,
DW_CLS_CONSTANT
,
DW_ATE_unsigned
,
0
);
newattr
(
die
,
DW_AT_byte_size
,
DW_CLS_CONSTANT
,
1
,
0
);
die
=
newdie
(
&
dwtypes
,
DW_ABRV_PTRTYPE
,
"<byte*>"
);
newrefattr
(
die
,
DW_AT_type
,
find
(
&
dwtypes
,
"<byte>"
));
genasmsym
(
defdwsymb
);
reversetree
(
&
dwtypes
.
child
);
reversetree
(
&
dwglobals
.
child
);
writeabbrev
();
writeabbrev
();
writelines
();
writelines
();
writeframes
();
writeframes
();
reversetree
(
&
dwroot
.
child
);
movetomodule
(
&
dwtypes
);
// TODO: put before functions
movetomodule
(
&
dwglobals
);
infoo
=
cpos
();
writeinfo
();
writeinfo
();
infoe
=
cpos
();
if
(
fwdcount
>
0
)
{
if
(
debug
[
'v'
])
Bprint
(
&
bso
,
"%5.2f dwarf pass 2.
\n
"
,
cputime
());
seek
(
cout
,
infoo
,
0
);
writeinfo
();
if
(
fwdcount
>
0
)
{
diag
(
"unresolved references after first dwarf info pass"
);
errorexit
();
}
if
(
infoe
!=
cpos
())
{
diag
(
"inconsistent second dwarf info pass"
);
errorexit
();
}
}
infosize
=
infoe
-
infoo
;
pubnameso
=
writepub
(
ispubname
);
pubtypeso
=
writepub
(
ispubtype
);
arangeso
=
writearanges
();
pubnamessize
=
pubtypeso
-
pubnameso
;
pubtypessize
=
arangeso
-
pubtypeso
;
arangessize
=
cpos
()
-
arangeso
;
}
}
/*
/*
...
@@ -1004,6 +1897,30 @@ dwarfaddelfheaders(void)
...
@@ -1004,6 +1897,30 @@ dwarfaddelfheaders(void)
sh
->
off
=
infoo
;
sh
->
off
=
infoo
;
sh
->
size
=
infosize
;
sh
->
size
=
infosize
;
sh
->
addralign
=
1
;
sh
->
addralign
=
1
;
if
(
pubnamessize
>
0
)
{
sh
=
newElfShdr
(
elfstrdbg
[
ElfStrDebugPubNames
]);
sh
->
type
=
SHT_PROGBITS
;
sh
->
off
=
pubnameso
;
sh
->
size
=
pubnamessize
;
sh
->
addralign
=
1
;
}
if
(
pubtypessize
>
0
)
{
sh
=
newElfShdr
(
elfstrdbg
[
ElfStrDebugPubTypes
]);
sh
->
type
=
SHT_PROGBITS
;
sh
->
off
=
pubtypeso
;
sh
->
size
=
pubtypessize
;
sh
->
addralign
=
1
;
}
if
(
arangessize
)
{
sh
=
newElfShdr
(
elfstrdbg
[
ElfStrDebugAranges
]);
sh
->
type
=
SHT_PROGBITS
;
sh
->
off
=
arangeso
;
sh
->
size
=
arangessize
;
sh
->
addralign
=
1
;
}
}
}
/*
/*
...
@@ -1021,23 +1938,48 @@ dwarfaddmachoheaders(void)
...
@@ -1021,23 +1938,48 @@ dwarfaddmachoheaders(void)
// have to be page aligned in the file.
// have to be page aligned in the file.
fakestart
=
abbrevo
&
~
0xfff
;
fakestart
=
abbrevo
&
~
0xfff
;
ms
=
newMachoSeg
(
"__DWARF"
,
4
);
ms
=
newMachoSeg
(
"__DWARF"
,
7
);
ms
->
fileoffset
=
fakestart
;
ms
->
fileoffset
=
fakestart
;
ms
->
filesize
=
abbrevo
-
fakestart
+
abbrevsize
+
linesize
+
framesize
+
infosize
;
ms
->
filesize
=
abbrevo
-
fakestart
;
msect
=
newMachoSect
(
ms
,
"__debug_abbrev"
);
msect
=
newMachoSect
(
ms
,
"__debug_abbrev"
);
msect
->
off
=
abbrevo
;
msect
->
off
=
abbrevo
;
msect
->
size
=
abbrevsize
;
msect
->
size
=
abbrevsize
;
ms
->
filesize
+=
msect
->
size
;
msect
=
newMachoSect
(
ms
,
"__debug_line"
);
msect
=
newMachoSect
(
ms
,
"__debug_line"
);
msect
->
off
=
lineo
;
msect
->
off
=
lineo
;
msect
->
size
=
linesize
;
msect
->
size
=
linesize
;
ms
->
filesize
+=
msect
->
size
;
msect
=
newMachoSect
(
ms
,
"__debug_frame"
);
msect
=
newMachoSect
(
ms
,
"__debug_frame"
);
msect
->
off
=
frameo
;
msect
->
off
=
frameo
;
msect
->
size
=
framesize
;
msect
->
size
=
framesize
;
ms
->
filesize
+=
msect
->
size
;
msect
=
newMachoSect
(
ms
,
"__debug_info"
);
msect
=
newMachoSect
(
ms
,
"__debug_info"
);
msect
->
off
=
infoo
;
msect
->
off
=
infoo
;
msect
->
size
=
infosize
;
msect
->
size
=
infosize
;
ms
->
filesize
+=
msect
->
size
;
if
(
pubnamessize
>
0
)
{
msect
=
newMachoSect
(
ms
,
"__debug_pubnames"
);
msect
->
off
=
pubnameso
;
msect
->
size
=
pubnamessize
;
ms
->
filesize
+=
msect
->
size
;
}
if
(
pubtypessize
>
0
)
{
msect
=
newMachoSect
(
ms
,
"__debug_pubtypes"
);
msect
->
off
=
pubtypeso
;
msect
->
size
=
pubtypessize
;
ms
->
filesize
+=
msect
->
size
;
}
if
(
arangessize
>
0
)
{
msect
=
newMachoSect
(
ms
,
"__debug_aranges"
);
msect
->
off
=
arangeso
;
msect
->
size
=
arangessize
;
ms
->
filesize
+=
msect
->
size
;
}
}
}
src/cmd/ld/dwarf.h
View file @
4228e622
...
@@ -2,25 +2,25 @@
...
@@ -2,25 +2,25 @@
// Use of this source code is governed by a BSD-style
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// license that can be found in the LICENSE file.
/*
/*
* Register 'f' symbol file fragments. Doing this while parsing the
* Register 'f' symbol file fragments. Doing this while parsing the
* .6 input saves a pass over the symbol table later.
* .6 input saves a pass over the symbol table later.
*/
*/
void
dwarfaddfrag
(
int
n
,
char
*
frag
);
void
dwarfaddfrag
(
int
n
,
char
*
frag
);
/*
* Add the dwarf section names to the ELF
* s[ection]h[eader]str[ing]tab.
*/
void
dwarfaddshstrings
(
Sym
*
shstrtab
);
/*
/*
* Emit debug_abbrevs, debug_info and debug_line sections to current
* Emit debug_abbrevs, debug_info and debug_line sections to current
* offset in cout.
* offset in cout.
*/
*/
void
dwarfemitdebugsections
(
void
);
void
dwarfemitdebugsections
(
void
);
/*
* Add the dwarf section names to the ELF
* s[ection]h[eader]str[ing]tab. Prerequisite for
* dwarfaddelfheaders().
*/
void
dwarfaddshstrings
(
Sym
*
shstrtab
);
/*
/*
* Add section headers pointing to the sections emitted in
* Add section headers pointing to the sections emitted in
* dwarfemitdebugsections.
* dwarfemitdebugsections.
...
...
src/cmd/ld/dwarf_defs.h
View file @
4228e622
...
@@ -55,6 +55,7 @@ enum
...
@@ -55,6 +55,7 @@ enum
DW_TAG_variant_part
=
0x33
,
DW_TAG_variant_part
=
0x33
,
DW_TAG_variable
=
0x34
,
DW_TAG_variable
=
0x34
,
DW_TAG_volatile_type
=
0x35
,
DW_TAG_volatile_type
=
0x35
,
// Dwarf3
DW_TAG_dwarf_procedure
=
0x36
,
DW_TAG_dwarf_procedure
=
0x36
,
DW_TAG_restrict_type
=
0x37
,
DW_TAG_restrict_type
=
0x37
,
DW_TAG_interface_type
=
0x38
,
DW_TAG_interface_type
=
0x38
,
...
@@ -65,6 +66,12 @@ enum
...
@@ -65,6 +66,12 @@ enum
DW_TAG_imported_unit
=
0x3d
,
DW_TAG_imported_unit
=
0x3d
,
DW_TAG_condition
=
0x3f
,
DW_TAG_condition
=
0x3f
,
DW_TAG_shared_type
=
0x40
,
DW_TAG_shared_type
=
0x40
,
// Dwarf4
DW_TAG_type_unit
=
0x41
,
DW_TAG_rvalue_reference_type
=
0x42
,
DW_TAG_template_alias
=
0x43
,
// User defined
DW_TAG_lo_user
=
0x4080
,
DW_TAG_lo_user
=
0x4080
,
DW_TAG_hi_user
=
0xffff
,
DW_TAG_hi_user
=
0xffff
,
...
@@ -84,7 +91,7 @@ enum
...
@@ -84,7 +91,7 @@ enum
DW_CLS_BLOCK
,
DW_CLS_BLOCK
,
DW_CLS_CONSTANT
,
DW_CLS_CONSTANT
,
DW_CLS_FLAG
,
DW_CLS_FLAG
,
DW_CLS_PTR
,
// lineptr, loclistptr, macptr, rangelistptr
DW_CLS_PTR
,
// lineptr, loclistptr, macptr, rangelistptr
DW_CLS_REFERENCE
,
DW_CLS_REFERENCE
,
DW_CLS_STRING
DW_CLS_STRING
};
};
...
@@ -151,6 +158,7 @@ enum
...
@@ -151,6 +158,7 @@ enum
DW_AT_variable_parameter
=
0x4b
,
// flag
DW_AT_variable_parameter
=
0x4b
,
// flag
DW_AT_virtuality
=
0x4c
,
// constant
DW_AT_virtuality
=
0x4c
,
// constant
DW_AT_vtable_elem_location
=
0x4d
,
// block, loclistptr
DW_AT_vtable_elem_location
=
0x4d
,
// block, loclistptr
// Dwarf3
DW_AT_allocated
=
0x4e
,
// block, constant, reference
DW_AT_allocated
=
0x4e
,
// block, constant, reference
DW_AT_associated
=
0x4f
,
// block, constant, reference
DW_AT_associated
=
0x4f
,
// block, constant, reference
DW_AT_data_location
=
0x50
,
// block
DW_AT_data_location
=
0x50
,
// block
...
@@ -178,6 +186,7 @@ enum
...
@@ -178,6 +186,7 @@ enum
DW_AT_elemental
=
0x66
,
// flag
DW_AT_elemental
=
0x66
,
// flag
DW_AT_pure
=
0x67
,
// flag
DW_AT_pure
=
0x67
,
// flag
DW_AT_recursive
=
0x68
,
// flag
DW_AT_recursive
=
0x68
,
// flag
DW_AT_lo_user
=
0x2000
,
// ---
DW_AT_lo_user
=
0x2000
,
// ---
DW_AT_hi_user
=
0x3fff
,
// ---
DW_AT_hi_user
=
0x3fff
,
// ---
...
@@ -358,6 +367,7 @@ enum
...
@@ -358,6 +367,7 @@ enum
DW_LANG_Fortran90
=
0x0008
,
DW_LANG_Fortran90
=
0x0008
,
DW_LANG_Pascal83
=
0x0009
,
DW_LANG_Pascal83
=
0x0009
,
DW_LANG_Modula2
=
0x000a
,
DW_LANG_Modula2
=
0x000a
,
// Dwarf3
DW_LANG_Java
=
0x000b
,
DW_LANG_Java
=
0x000b
,
DW_LANG_C99
=
0x000c
,
DW_LANG_C99
=
0x000c
,
DW_LANG_Ada95
=
0x000d
,
DW_LANG_Ada95
=
0x000d
,
...
@@ -367,7 +377,8 @@ enum
...
@@ -367,7 +377,8 @@ enum
DW_LANG_ObjC_plus_plus
=
0x0011
,
DW_LANG_ObjC_plus_plus
=
0x0011
,
DW_LANG_UPC
=
0x0012
,
DW_LANG_UPC
=
0x0012
,
DW_LANG_D
=
0x0013
,
DW_LANG_D
=
0x0013
,
DW_LANG_Python
=
0x0014
,
// DWARF4
// Dwarf4
DW_LANG_Python
=
0x0014
,
DW_LANG_lo_user
=
0x8000
,
DW_LANG_lo_user
=
0x8000
,
DW_LANG_Go
=
0x8015
,
// TODO(lvd) Temporary
DW_LANG_Go
=
0x8015
,
// TODO(lvd) Temporary
...
@@ -428,6 +439,7 @@ enum
...
@@ -428,6 +439,7 @@ enum
DW_LNS_set_basic_block
=
0x07
,
DW_LNS_set_basic_block
=
0x07
,
DW_LNS_const_add_pc
=
0x08
,
DW_LNS_const_add_pc
=
0x08
,
DW_LNS_fixed_advance_pc
=
0x09
,
DW_LNS_fixed_advance_pc
=
0x09
,
// Dwarf3
DW_LNS_set_prologue_end
=
0x0a
,
DW_LNS_set_prologue_end
=
0x0a
,
DW_LNS_set_epilogue_begin
=
0x0b
,
DW_LNS_set_epilogue_begin
=
0x0b
,
DW_LNS_set_isa
=
0x0c
,
DW_LNS_set_isa
=
0x0c
,
...
...
src/cmd/ld/elf.h
View file @
4228e622
...
@@ -975,5 +975,4 @@ void elfsetstring(char*, int);
...
@@ -975,5 +975,4 @@ void elfsetstring(char*, int);
* May waste some.
* May waste some.
* On FreeBSD, cannot be larger than a page.
* On FreeBSD, cannot be larger than a page.
*/
*/
#define ELFRESERVE 2048
#define ELFRESERVE 3072
src/pkg/runtime/type.go
View file @
4228e622
...
@@ -9,6 +9,7 @@
...
@@ -9,6 +9,7 @@
* data structures and must be kept in sync with this file:
* data structures and must be kept in sync with this file:
*
*
* ../../cmd/gc/reflect.c
* ../../cmd/gc/reflect.c
* ../../cmd/ld/dwarf.c
* ../reflect/type.go
* ../reflect/type.go
* type.h
* type.h
*/
*/
...
...
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