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 @@
// Use of this source code is governed by a BSD-style
// 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 "lib.h"
#include "../ld/dwarf.h"
...
...
@@ -17,10 +26,16 @@ static vlong abbrevo;
static
vlong
abbrevsize
;
static
vlong
lineo
;
static
vlong
linesize
;
static
vlong
infoo
;
static
vlong
infoo
;
// also the base for DWDie->offs and reference attributes.
static
vlong
infosize
;
static
vlong
frameo
;
static
vlong
framesize
;
static
vlong
pubnameso
;
static
vlong
pubnamessize
;
static
vlong
pubtypeso
;
static
vlong
pubtypessize
;
static
vlong
arangeso
;
static
vlong
arangessize
;
/*
* Basic I/O
...
...
@@ -39,7 +54,6 @@ addrput(vlong addr)
}
}
static
int
uleb128enc
(
uvlong
v
,
char
*
dst
)
{
...
...
@@ -106,17 +120,34 @@ struct DWAttrForm {
uint8
form
;
};
// index into the abbrevs table below.
// Index into the abbrevs table below.
// Keep in sync with ispubname() and ispubtype() below.
enum
{
DW_ABRV_NULL
,
DW_ABRV_COMPUNIT
,
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
};
typedef
struct
DWAbbrev
DWAbbrev
;
struct
DWAbbrev
{
st
atic
st
ruct
DWAbbrev
{
uint8
tag
;
uint8
children
;
DWAttrForm
attr
[
30
];
...
...
@@ -135,10 +166,137 @@ struct DWAbbrev {
},
/* FUNCTION */
{
DW_TAG_subprogram
,
DW_CHILDREN_
no
,
DW_TAG_subprogram
,
DW_CHILDREN_
yes
,
DW_AT_name
,
DW_FORM_string
,
DW_AT_low_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
},
};
...
...
@@ -154,8 +312,8 @@ writeabbrev(void)
uleb128put
(
i
);
uleb128put
(
abbrevs
[
i
].
tag
);
cput
(
abbrevs
[
i
].
children
);
// 0 is not a valid attr or form,
so we can treat this a
s
// a string
// 0 is not a valid attr or form,
and DWAbbrev.attr i
s
//
0-terminated, so we can treat it as
a string
n
=
strlen
((
char
*
)
abbrevs
[
i
].
attr
)
/
2
;
strnput
((
char
*
)
abbrevs
[
i
].
attr
,
(
n
+
1
)
*
sizeof
(
DWAttrForm
));
...
...
@@ -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
// data the data, for all others, value is the whole thing and data is
// null.
// data the data, for _reference, value is 0 and data is a DWDie* to
// the referenced instance, for all others, value is the whole thing
// and data is null.
typedef
struct
DWAttr
DWAttr
;
struct
DWAttr
{
...
...
@@ -187,21 +362,20 @@ struct DWDie {
DWDie
*
link
;
DWDie
*
child
;
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
;
static
DWDie
*
newdie
(
DWDie
*
link
,
int
abbrev
)
{
DWDie
*
die
;
/*
* Root DIEs for compilation units, types and global variables.
*/
die
=
mal
(
sizeof
*
die
);
die
->
abbrev
=
abbrev
;
die
->
link
=
link
;
return
die
;
}
static
DWDie
dwroot
;
static
DWDie
dwtypes
;
static
DWDie
dwglobals
;
static
DWAttr
*
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
;
}
// 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
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
);
break
;
case
DW_FORM_strp
:
// string
case
DW_FORM_ref_addr
:
// reference
case
DW_FORM_ref1
:
// reference
case
DW_FORM_ref_addr
:
// reference to a DIE in the .info section
if
(
data
==
nil
)
{
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_ref4
:
// reference
case
DW_FORM_ref8
:
// reference
case
DW_FORM_ref_udata
:
// reference
case
DW_FORM_strp
:
// string
case
DW_FORM_indirect
:
// (see Section 7.5.3)
default:
diag
(
"Unsupported atribute form %d / class %d"
,
form
,
cls
);
...
...
@@ -330,6 +618,7 @@ putdies(DWDie* die)
static
void
putdie
(
DWDie
*
die
)
{
die
->
offs
=
cpos
()
-
infoo
;
uleb128put
(
die
->
abbrev
);
putattrs
(
die
->
abbrev
,
die
->
attr
);
if
(
abbrevs
[
die
->
abbrev
].
children
)
{
...
...
@@ -344,8 +633,8 @@ reverselist(DWDie** list)
DWDie
*
curr
,
*
prev
;
curr
=
*
list
;
prev
=
0
;
while
(
curr
)
{
prev
=
nil
;
while
(
curr
!=
nil
)
{
DWDie
*
next
=
curr
->
link
;
curr
->
link
=
prev
;
prev
=
curr
;
...
...
@@ -360,11 +649,397 @@ reversetree(DWDie** list)
DWDie
*
die
;
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
);
}
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.
*/
...
...
@@ -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
)
{
char
*
unitname
;
Linehist
*
lh
;
for
(;
a
;
a
=
a
->
link
)
...
...
@@ -531,8 +1209,6 @@ inithist(Auto *a)
return
0
;
}
unitname
=
decodez
(
a
->
asym
->
name
);
// Clear the history.
clearhistfile
();
includetop
=
0
;
...
...
@@ -558,7 +1234,6 @@ inithist(Auto *a)
checknesting
();
includestack
[
includetop
].
file
=
f
;
includestack
[
includetop
].
line
=
1
;
}
absline
=
a
->
aoffset
;
}
else
if
(
a
->
type
==
D_FILE1
)
{
// 'Z'
...
...
@@ -580,7 +1255,7 @@ inithist(Auto *a)
linehist
->
file
=
includestack
[
includetop
].
file
;
linehist
->
line
=
includestack
[
includetop
].
line
;
}
return
unitname
;
return
1
;
}
static
Linehist
*
...
...
@@ -635,6 +1310,23 @@ putpclcdelta(vlong delta_pc, vlong delta_lc)
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.
...
...
@@ -642,7 +1334,7 @@ putpclcdelta(vlong delta_pc, vlong delta_lc)
// flush previous compilation unit.
static
void
flushunit
(
vlong
pc
,
vlong
unitstart
)
flushunit
(
DWDie
*
dwinfo
,
vlong
pc
,
vlong
unitstart
)
{
vlong
here
;
...
...
@@ -669,12 +1361,13 @@ writelines(void)
{
Prog
*
q
;
Sym
*
s
;
char
*
unitname
;
Auto
*
a
;
vlong
unitstart
;
vlong
pc
,
epc
,
lc
,
llc
,
lline
;
int
currfile
;
int
i
;
int
i
,
lang
;
Linehist
*
lh
;
DWDie
*
dwinfo
,
*
dwfunc
,
*
dwvar
;
unitstart
=
-
1
;
epc
=
pc
=
0
;
...
...
@@ -682,32 +1375,39 @@ writelines(void)
llc
=
1
;
currfile
=
-
1
;
lineo
=
cpos
();
dwinfo
=
nil
;
for
(
cursym
=
textp
;
cursym
!=
nil
;
cursym
=
cursym
->
next
)
{
s
=
cursym
;
// Look for history stack. If we find one,
// 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
();
if
(
debug
[
'v'
]
>
1
)
{
print
(
"dwarf writelines found %s
\n
"
,
unitname
);
print
(
"dwarf writelines found %s
\n
"
,
histfile
[
1
]
);
Linehist
*
lh
;
for
(
lh
=
linehist
;
lh
;
lh
=
lh
->
link
)
print
(
"
\t
%8lld: [%4lld]%s
\n
"
,
lh
->
absline
,
lh
->
line
,
histfile
[
lh
->
file
]);
}
dwinfo
=
newdie
(
dwinfo
,
DW_ABRV_COMPUNIT
);
newattr
(
dwinfo
,
DW_AT_name
,
DW_CLS_STRING
,
strlen
(
unitname
),
unitname
);
newattr
(
dwinfo
,
DW_AT_language
,
DW_CLS_CONSTANT
,
guesslang
(
unitname
),
0
);
lang
=
guesslang
(
histfile
[
1
]);
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_low_pc
,
DW_CLS_ADDRESS
,
s
->
text
->
pc
,
0
);
// Write .debug_line Line Number Program Header (sec 6.2.4)
// Fields marked with (*) must be changed for 64-bit dwarf
LPUT
(
0
);
// unit_length (*), will be filled in later.
WPUT
(
3
);
// version
LPUT
(
11
);
// header_length (*)
WPUT
(
3
);
// dwarf version (appendix F)
LPUT
(
11
);
// header_length (*), starting here.
cput
(
1
);
// minimum_instruction_length
cput
(
1
);
// default_is_stmt
cput
(
LINE_BASE
);
// line_base
...
...
@@ -719,6 +1419,8 @@ writelines(void)
cput
(
1
);
// standard_opcode_lengths[4]
cput
(
0
);
// include_directories (empty)
cput
(
0
);
// file_names (empty) (emitted by DW_LNE's below)
// header_length ends here.
for
(
i
=
1
;
i
<
histfilesize
;
i
++
)
{
cput
(
0
);
// start extended opcode
uleb128put
(
1
+
strlen
(
histfile
[
i
])
+
4
);
...
...
@@ -745,11 +1447,12 @@ writelines(void)
continue
;
}
dwinfo
->
child
=
newdie
(
dwinfo
->
child
,
DW_ABRV_FUNCTION
);
newattr
(
dwinfo
->
child
,
DW_AT_name
,
DW_CLS_STRING
,
strlen
(
s
->
name
),
s
->
name
);
newattr
(
dwinfo
->
child
,
DW_AT_low_pc
,
DW_CLS_ADDRESS
,
s
->
value
,
0
);
dwfunc
=
newdie
(
dwinfo
,
DW_ABRV_FUNCTION
,
s
->
name
);
newattr
(
dwfunc
,
DW_AT_low_pc
,
DW_CLS_ADDRESS
,
s
->
value
,
0
);
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
)
{
lh
=
searchhist
(
q
->
line
);
...
...
@@ -757,8 +1460,9 @@ writelines(void)
diag
(
"corrupt history or bad absolute line: %P"
,
q
);
continue
;
}
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
;
}
...
...
@@ -778,9 +1482,24 @@ writelines(void)
lc
=
q
->
line
;
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
;
}
...
...
@@ -824,20 +1543,20 @@ writeframes(void)
frameo
=
cpos
();
// Emit the CIE, Section 6.4.1
LPUT
(
CIERESERVE
);
// initial length, must be multiple of PtrSize
LPUT
(
0xffffffff
);
// cid.
cput
(
3
);
// dwarf version
cput
(
0
);
// augmentation ""
uleb128put
(
1
);
// code_alignment_factor
LPUT
(
CIERESERVE
);
// initial length, must be multiple of PtrSize
LPUT
(
0xffffffff
);
// cid.
cput
(
3
);
// dwarf version (appendix F)
cput
(
0
);
// augmentation ""
uleb128put
(
1
);
// code_alignment_factor
sleb128put
(
DATAALIGNMENTFACTOR
);
// guess
uleb128put
(
FAKERETURNCOLUMN
);
// return_address_register
uleb128put
(
FAKERETURNCOLUMN
);
// return_address_register
cput
(
DW_CFA_def_cfa
);
uleb128put
(
DWARFREGSP
);
// register SP (**ABI-dependent, defined in l.h)
uleb128put
(
PtrSize
);
// offset
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.
pad
=
CIERESERVE
+
frameo
+
4
-
cpos
();
...
...
@@ -866,7 +1585,6 @@ writeframes(void)
for
(
q
=
p
;
q
->
link
!=
P
;
q
=
q
->
link
)
{
if
(
q
->
spadj
==
0
)
continue
;
cfa
+=
q
->
spadj
;
putpccfadelta
(
q
->
link
->
pc
-
pc
,
cfa
);
pc
=
q
->
link
->
pc
;
...
...
@@ -896,47 +1614,222 @@ writeframes(void)
/*
* Walk DWarfDebugInfoEntries, and emit .debug_info
*/
enum
{
COMPUNITHEADERSIZE
=
4
+
2
+
4
+
1
};
static
void
writeinfo
(
void
)
{
DWDie
*
compunit
;
vlong
unitstart
;
vlong
unitstart
,
here
;
reversetree
(
&
dwinfo
)
;
fwdcount
=
0
;
infoo
=
cpos
();
for
(
compunit
=
dwinfo
;
compunit
;
compunit
=
compunit
->
link
)
{
for
(
compunit
=
dwroot
.
child
;
compunit
;
compunit
=
compunit
->
link
)
{
unitstart
=
cpos
();
// Write .debug_info Compilation Unit Header (sec 7.5.1)
// Fields marked with (*) must be changed for 64-bit dwarf
LPUT
(
0
);
// unit_length (*), will be filled in later.
WPUT
(
3
);
// version
LPUT
(
0
);
// debug_abbrev_offset (*)
cput
(
PtrSize
);
// address_size
// This must match COMPUNITHEADERSIZE above.
LPUT
(
0
);
// unit_length (*), will be filled in later.
WPUT
(
3
);
// dwarf version (appendix F)
LPUT
(
0
);
// debug_abbrev_offset (*)
cput
(
PtrSize
);
// address_size
putdie
(
compunit
);
cflush
();
vlong
here
=
cpos
();
here
=
cpos
();
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
();
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
();
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
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
();
writelines
();
writeframes
();
reversetree
(
&
dwroot
.
child
);
movetomodule
(
&
dwtypes
);
// TODO: put before functions
movetomodule
(
&
dwglobals
);
infoo
=
cpos
();
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)
sh
->
off
=
infoo
;
sh
->
size
=
infosize
;
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)
// have to be page aligned in the file.
fakestart
=
abbrevo
&
~
0xfff
;
ms
=
newMachoSeg
(
"__DWARF"
,
4
);
ms
=
newMachoSeg
(
"__DWARF"
,
7
);
ms
->
fileoffset
=
fakestart
;
ms
->
filesize
=
abbrevo
-
fakestart
+
abbrevsize
+
linesize
+
framesize
+
infosize
;
ms
->
filesize
=
abbrevo
-
fakestart
;
msect
=
newMachoSect
(
ms
,
"__debug_abbrev"
);
msect
->
off
=
abbrevo
;
msect
->
size
=
abbrevsize
;
ms
->
filesize
+=
msect
->
size
;
msect
=
newMachoSect
(
ms
,
"__debug_line"
);
msect
->
off
=
lineo
;
msect
->
size
=
linesize
;
ms
->
filesize
+=
msect
->
size
;
msect
=
newMachoSect
(
ms
,
"__debug_frame"
);
msect
->
off
=
frameo
;
msect
->
size
=
framesize
;
ms
->
filesize
+=
msect
->
size
;
msect
=
newMachoSect
(
ms
,
"__debug_info"
);
msect
->
off
=
infoo
;
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 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
* Register 'f' symbol file fragments. Doing this while parsing the
* .6 input saves a pass over the symbol table later.
*/
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
* offset in cout.
*/
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
* dwarfemitdebugsections.
...
...
src/cmd/ld/dwarf_defs.h
View file @
4228e622
...
...
@@ -55,6 +55,7 @@ enum
DW_TAG_variant_part
=
0x33
,
DW_TAG_variable
=
0x34
,
DW_TAG_volatile_type
=
0x35
,
// Dwarf3
DW_TAG_dwarf_procedure
=
0x36
,
DW_TAG_restrict_type
=
0x37
,
DW_TAG_interface_type
=
0x38
,
...
...
@@ -65,6 +66,12 @@ enum
DW_TAG_imported_unit
=
0x3d
,
DW_TAG_condition
=
0x3f
,
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_hi_user
=
0xffff
,
...
...
@@ -84,7 +91,7 @@ enum
DW_CLS_BLOCK
,
DW_CLS_CONSTANT
,
DW_CLS_FLAG
,
DW_CLS_PTR
,
// lineptr, loclistptr, macptr, rangelistptr
DW_CLS_PTR
,
// lineptr, loclistptr, macptr, rangelistptr
DW_CLS_REFERENCE
,
DW_CLS_STRING
};
...
...
@@ -151,6 +158,7 @@ enum
DW_AT_variable_parameter
=
0x4b
,
// flag
DW_AT_virtuality
=
0x4c
,
// constant
DW_AT_vtable_elem_location
=
0x4d
,
// block, loclistptr
// Dwarf3
DW_AT_allocated
=
0x4e
,
// block, constant, reference
DW_AT_associated
=
0x4f
,
// block, constant, reference
DW_AT_data_location
=
0x50
,
// block
...
...
@@ -178,6 +186,7 @@ enum
DW_AT_elemental
=
0x66
,
// flag
DW_AT_pure
=
0x67
,
// flag
DW_AT_recursive
=
0x68
,
// flag
DW_AT_lo_user
=
0x2000
,
// ---
DW_AT_hi_user
=
0x3fff
,
// ---
...
...
@@ -358,6 +367,7 @@ enum
DW_LANG_Fortran90
=
0x0008
,
DW_LANG_Pascal83
=
0x0009
,
DW_LANG_Modula2
=
0x000a
,
// Dwarf3
DW_LANG_Java
=
0x000b
,
DW_LANG_C99
=
0x000c
,
DW_LANG_Ada95
=
0x000d
,
...
...
@@ -367,7 +377,8 @@ enum
DW_LANG_ObjC_plus_plus
=
0x0011
,
DW_LANG_UPC
=
0x0012
,
DW_LANG_D
=
0x0013
,
DW_LANG_Python
=
0x0014
,
// DWARF4
// Dwarf4
DW_LANG_Python
=
0x0014
,
DW_LANG_lo_user
=
0x8000
,
DW_LANG_Go
=
0x8015
,
// TODO(lvd) Temporary
...
...
@@ -428,6 +439,7 @@ enum
DW_LNS_set_basic_block
=
0x07
,
DW_LNS_const_add_pc
=
0x08
,
DW_LNS_fixed_advance_pc
=
0x09
,
// Dwarf3
DW_LNS_set_prologue_end
=
0x0a
,
DW_LNS_set_epilogue_begin
=
0x0b
,
DW_LNS_set_isa
=
0x0c
,
...
...
src/cmd/ld/elf.h
View file @
4228e622
...
...
@@ -975,5 +975,4 @@ void elfsetstring(char*, int);
* May waste some.
* 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 @@
* data structures and must be kept in sync with this file:
*
* ../../cmd/gc/reflect.c
* ../../cmd/ld/dwarf.c
* ../reflect/type.go
* 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