Skip to content

Commit

Permalink
proc/gdbserial: refactor parsing of key-value pairs from gdb protocol (
Browse files Browse the repository at this point in the history
…#3574)

The gdb remote serial protocol returns in several places a list of key
value pair in the form key1:value1;key2:value2;...;keyN:valueN.
We had ad-hoc parsers for this in three places, this commit
consolidates the parser in a single utility object.
  • Loading branch information
aarzilli authored Nov 20, 2023
1 parent a5b03f0 commit 721a0d7
Showing 1 changed file with 39 additions and 51 deletions.
90 changes: 39 additions & 51 deletions pkg/proc/gdbserial/gdbserver_conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -758,24 +758,9 @@ func (conn *gdbConn) parseStopPacket(resp []byte, threadID string, tu *threadUpd
var metype int
var medata = make([]uint64, 0, 10)

buf := resp[3:]
for buf != nil {
colon := bytes.Index(buf, []byte{':'})
if colon < 0 {
break
}
key := buf[:colon]
buf = buf[colon+1:]

semicolon := bytes.Index(buf, []byte{';'})
var value []byte
if semicolon < 0 {
value = buf
buf = nil
} else {
value = buf[:semicolon]
buf = buf[semicolon+1:]
}
csp := colonSemicolonParser{buf: resp[3:]}
for csp.next() {
key, value := csp.key, csp.value

switch string(key) {
case "thread":
Expand Down Expand Up @@ -872,21 +857,9 @@ func (conn *gdbConn) queryProcessInfo(pid int) (map[string]string, error) {

pi := make(map[string]string)

for len(resp) > 0 {
semicolon := bytes.Index(resp, []byte{';'})
keyval := resp
if semicolon >= 0 {
keyval = resp[:semicolon]
resp = resp[semicolon+1:]
}

colon := bytes.Index(keyval, []byte{':'})
if colon < 0 {
continue
}

key := string(keyval[:colon])
value := string(keyval[colon+1:])
csp := colonSemicolonParser{buf: resp}
for csp.next() {
key, value := string(csp.key), string(csp.value)

switch key {
case "name":
Expand Down Expand Up @@ -1235,24 +1208,9 @@ func (conn *gdbConn) memoryRegionInfo(addr uint64) (*memoryRegionInfo, error) {

mri := &memoryRegionInfo{}

buf := resp
for len(buf) > 0 {
colon := bytes.Index(buf, []byte{':'})
if colon < 0 {
break
}
key := buf[:colon]
buf = buf[colon+1:]

semicolon := bytes.Index(buf, []byte{';'})
var value []byte
if semicolon < 0 {
value = buf
buf = nil
} else {
value = buf[:semicolon]
buf = buf[semicolon+1:]
}
csp := colonSemicolonParser{buf: resp}
for csp.next() {
key, value := csp.key, csp.value

switch string(key) {
case "start":
Expand Down Expand Up @@ -1549,3 +1507,33 @@ func checksum(packet []byte) (sum uint8) {
}
return sum
}

// colonSemicolonParser parses a string in the form:
//
// key1:value1;key2:value2;...;keyN:valueN
type colonSemicolonParser struct {
buf []byte
key, value []byte
}

func (csp *colonSemicolonParser) next() bool {
if len(csp.buf) == 0 {
return false
}
colon := bytes.IndexByte(csp.buf, ':')
if colon < 0 {
return false
}
csp.key = csp.buf[:colon]
csp.buf = csp.buf[colon+1:]

semicolon := bytes.IndexByte(csp.buf, ';')
if semicolon < 0 {
csp.value = csp.buf
csp.buf = nil
} else {
csp.value = csp.buf[:semicolon]
csp.buf = csp.buf[semicolon+1:]
}
return true
}

0 comments on commit 721a0d7

Please sign in to comment.