Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(12)

Side by Side Diff: src/cmd/ld/lib.c

Issue 88190043: code review 88190043: liblink, cmd/ld: reenable nosplit checking and test (Closed)
Patch Set: diff -r 738877993c83 https://code.google.com/p/go/ Created 10 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Derived from Inferno utils/6l/obj.c and utils/6l/span.c 1 // Derived from Inferno utils/6l/obj.c and utils/6l/span.c
2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/obj.c
3 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c 3 // http://code.google.com/p/inferno-os/source/browse/utils/6l/span.c
4 // 4 //
5 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
6 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
7 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 1997-1999 Vita Nuova Limited
8 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov a.com) 8 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuov a.com)
9 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2004,2006 Bruce Ellis
10 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
(...skipping 999 matching lines...) Expand 10 before | Expand all | Expand 10 after
1010 if(thechar == '5') 1010 if(thechar == '5')
1011 return 0; 1011 return 0;
1012 return RegSize; 1012 return RegSize;
1013 } 1013 }
1014 1014
1015 void 1015 void
1016 dostkcheck(void) 1016 dostkcheck(void)
1017 { 1017 {
1018 Chain ch; 1018 Chain ch;
1019 LSym *s; 1019 LSym *s;
1020 » 1020
1021 morestack = linklookup(ctxt, "runtime.morestack", 0); 1021 morestack = linklookup(ctxt, "runtime.morestack", 0);
1022 newstack = linklookup(ctxt, "runtime.newstack", 0); 1022 newstack = linklookup(ctxt, "runtime.newstack", 0);
1023 1023
1024 // TODO
1025 // First the nosplits on their own. 1024 // First the nosplits on their own.
1026 for(s = ctxt->textp; s != nil; s = s->next) { 1025 for(s = ctxt->textp; s != nil; s = s->next) {
1027 » » if(s->text == nil || s->text->link == nil || (ctxt->arch->textfl ag(s->text) & NOSPLIT) == 0) 1026 » » if(s->nosplit == 0)
1028 continue; 1027 continue;
1029 ctxt->cursym = s; 1028 ctxt->cursym = s;
1030 ch.up = nil; 1029 ch.up = nil;
1031 ch.sym = s; 1030 ch.sym = s;
1032 ch.limit = StackLimit - callsize(); 1031 ch.limit = StackLimit - callsize();
1033 stkcheck(&ch, 0); 1032 stkcheck(&ch, 0);
1034 s->stkcheck = 1; 1033 s->stkcheck = 1;
iant 2014/04/16 21:29:09 I don't think you need to set the stkcheck field h
rsc 2014/04/16 22:59:16 Done.
1035 } 1034 }
1036 ········ 1035 ········
1037 // Check calling contexts. 1036 // Check calling contexts.
1038 // Some nosplits get called a little further down, 1037 // Some nosplits get called a little further down,
1039 // like newproc and deferproc. We could hard-code 1038 // like newproc and deferproc. We could hard-code
1040 // that knowledge but it's more robust to look at 1039 // that knowledge but it's more robust to look at
1041 // the actual call sites. 1040 // the actual call sites.
1042 for(s = ctxt->textp; s != nil; s = s->next) { 1041 for(s = ctxt->textp; s != nil; s = s->next) {
1043 » » if(s->text == nil || s->text->link == nil || (ctxt->arch->textfl ag(s->text) & NOSPLIT) != 0) 1042 » » if(s->nosplit != 0)
1044 continue; 1043 continue;
1045 ctxt->cursym = s; 1044 ctxt->cursym = s;
1046 ch.up = nil; 1045 ch.up = nil;
1047 ch.sym = s; 1046 ch.sym = s;
1048 ch.limit = StackLimit - callsize(); 1047 ch.limit = StackLimit - callsize();
1049 stkcheck(&ch, 0); 1048 stkcheck(&ch, 0);
1050 } 1049 }
1051 } 1050 }
1052 1051
1053 static int 1052 static int
1054 stkcheck(Chain *up, int depth) 1053 stkcheck(Chain *up, int depth)
1055 { 1054 {
1056 Chain ch, ch1; 1055 Chain ch, ch1;
1057 Prog *p;
1058 LSym *s; 1056 LSym *s;
1059 » int limit, prolog; 1057 » int limit, prolog, i, end;
1058 » Reloc *r;
1059 » Pciter pcsp;
1060 ········ 1060 ········
1061 limit = up->limit; 1061 limit = up->limit;
1062 s = up->sym; 1062 s = up->sym;
1063 p = s->text;
1064 ········ 1063 ········
1065 » // Small optimization: don't repeat work at top. 1064 » // Don't duplicate work: only need to consider each
1066 » if(s->stkcheck && limit == StackLimit-callsize()) 1065 » // function at top of safe zone once.
1067 » » return 0; 1066 » if(limit == StackLimit-callsize()) {
1067 » » if(s->stkcheck)
1068 » » » return 0;
1069 » » s->stkcheck = 1;
1070 » }
1068 ········ 1071 ········
1069 if(depth > 100) { 1072 if(depth > 100) {
1070 diag("nosplit stack check too deep"); 1073 diag("nosplit stack check too deep");
1071 stkbroke(up, 0); 1074 stkbroke(up, 0);
1072 return -1; 1075 return -1;
1073 } 1076 }
1074 1077 »
iant 2014/04/16 21:29:09 Trailing whitespace?
rsc 2014/04/16 22:59:16 Done, but everywhere in the file (sorry).
1075 » if(p == nil || p->link == nil) { 1078 » if(s->external || s->pcln == nil) {
1076 // external function. 1079 // external function.
1077 // should never be called directly. 1080 // should never be called directly.
1078 // only diagnose the direct caller. 1081 // only diagnose the direct caller.
1079 if(depth == 1 && s->type != SXREF) 1082 if(depth == 1 && s->type != SXREF)
1080 diag("call to external function %s", s->name); 1083 diag("call to external function %s", s->name);
1081 return -1; 1084 return -1;
1082 } 1085 }
1083 1086
1084 if(limit < 0) { 1087 if(limit < 0) {
1085 stkbroke(up, limit); 1088 stkbroke(up, limit);
1086 return -1; 1089 return -1;
1087 } 1090 }
1088 1091
1089 // morestack looks like it calls functions, 1092 // morestack looks like it calls functions,
1090 // but it switches the stack pointer first. 1093 // but it switches the stack pointer first.
1091 if(s == morestack) 1094 if(s == morestack)
1092 return 0; 1095 return 0;
1093 1096
1094 ch.up = up; 1097 ch.up = up;
1095 » prolog = (ctxt->arch->textflag(s->text) & NOSPLIT) == 0; 1098 » prolog = !s->nosplit;
iant 2014/04/16 21:29:09 Argh, negating a flag expressed as a negative.
rsc 2014/04/16 22:59:16 I know, but NOSPLIT is the name of the assembler d
1096 » for(p = s->text; p != P; p = p->link) { 1099 » pciterinit(&pcsp, &s->pcln->pcsp);
1097 » » limit -= p->spadj; 1100
1098 » » if(prolog && p->spadj != 0) { 1101 » // walk relocs, advancing spadj table at the same time
1099 » » » // The first stack adjustment in a function with a 1102 » r = nil;
1100 » » » // split-checking prologue marks the end of the 1103 » for(i = 0; i <= s->nr; i++) {
1101 » » » // prologue. Assuming the split check is correct, 1104 » » if(i == s->nr)
1102 » » » // after the adjustment there should still be at least 1105 » » » end = s->size;
1103 » » » // StackLimit bytes available below the stack pointer. 1106 » » else {
1104 » » » // If this is not the top call in the chain, no need 1107 » » » r = &s->r[i];
1105 » » » // to duplicate effort, so just stop. 1108 » » » if(r->type != R_CALL && r->type != R_CALLIND)
1106 » » » if(depth > 0) 1109 » » » » continue;
1107 » » » » return 0; 1110 » » » end = r->off;
1108 » » » prolog = 0;
1109 » » » limit = StackLimit;
1110 } 1111 }
1111 » » if(limit < 0) { 1112 » » while(!pcsp.done && pcsp.pc < end) {
1112 » » » stkbroke(up, limit); 1113 » » » if(prolog && pcsp.value > 0) {
1113 » » » return -1; 1114 » » » » // The first stack adjustment in a function with a
1115 » » » » // split-checking prologue marks the end of the
1116 » » » » // prologue. Assuming the split check is correc t,
1117 » » » » // after the adjustment there should still be at least
1118 » » » » // StackLimit bytes available below the stack po inter.
1119 » » » » // If this is not the top call in the chain, no need
1120 » » » » // to duplicate effort, so just stop.
1121 » » » » if(depth > 0)
1122 » » » » » return 0;
1123 » » » » prolog = 0;
1124 » » » » limit = StackLimit + pcsp.value;
1125 » » » }
1126 » » » if(limit - pcsp.value < 0) {
1127 » » » » stkbroke(up, limit - pcsp.value);
1128 » » » » return -1;
1129 » » » }
1130 » » » if(end < pcsp.nextpc)
iant 2014/04/16 21:29:09 Why check this both here and at the top of the loo
rsc 2014/04/16 22:59:16 It made sense at the time (yesterday morning). Not
rsc 2014/04/17 00:28:01 This code is tricky because it needs to iterate ov
1131 » » » » break;
1132 » » » pciternext(&pcsp);
1114 } 1133 }
1115 » » if(ctxt->arch->iscall(p)) { 1134 » » if(i == s->nr)
1116 » » » limit -= callsize(); 1135 » » » break;
1117 » » » ch.limit = limit; 1136
1118 » » » if(p->to.type == D_BRANCH) { 1137 » » ch.limit = limit - pcsp.value - callsize();
1119 » » » » // Direct call. 1138 » » if(r->type == R_CALL) {
1120 » » » » ch.sym = p->to.sym; 1139 » » » // Direct call.
1121 » » » » if(stkcheck(&ch, depth+1) < 0) 1140 » » » ch.sym = r->sym;
1122 » » » » » return -1; 1141 » » » if(stkcheck(&ch, depth+1) < 0)
1123 » » » } else { 1142 » » » » return -1;
1124 » » » » // Indirect call. Assume it is a splitting func tion, 1143 » » » if(prolog && s->locals == 0 && strstr(r->sym->name, "mor estack")) {
1125 » » » » // so we have to make sure it can call morestack . 1144 » » » » prolog = 0;
1126 » » » » limit -= callsize(); 1145 » » » » limit = StackLimit;
1127 » » » » ch.sym = nil;
1128 » » » » ch1.limit = limit;
1129 » » » » ch1.up = &ch;
1130 » » » » ch1.sym = morestack;
1131 » » » » if(stkcheck(&ch1, depth+2) < 0)
1132 » » » » » return -1;
1133 » » » » limit += callsize();
1134 } 1146 }
1135 » » » limit += callsize(); 1147 » » } else {
1148 » » » // Indirect call. Assume it is a splitting function,
1149 » » » // so we have to make sure it can call morestack.
1150 » » » ch.sym = nil;
1151 » » » ch1.limit = ch.limit - callsize(); // for morestack in c alled prologue
1152 » » » ch1.up = &ch;
1153 » » » ch1.sym = morestack;
1154 » » » if(stkcheck(&ch1, depth+2) < 0)
iant 2014/04/16 21:29:09 Because the code checks explicitly for morestack a
rsc 2014/04/16 22:59:16 Yes, to get a nice diagnostic that tells you that
1155 » » » » return -1;
1136 } 1156 }
1137 ················
1138 } 1157 }
1158
1139 return 0; 1159 return 0;
1140 } 1160 }
1141 1161
1142 static void 1162 static void
1143 stkbroke(Chain *ch, int limit) 1163 stkbroke(Chain *ch, int limit)
1144 { 1164 {
1145 diag("nosplit stack overflow"); 1165 diag("nosplit stack overflow");
1146 stkprint(ch, limit); 1166 stkprint(ch, limit);
1147 } 1167 }
1148 1168
1149 static void 1169 static void
1150 stkprint(Chain *ch, int limit) 1170 stkprint(Chain *ch, int limit)
1151 { 1171 {
1152 char *name; 1172 char *name;
1153 1173
1154 if(ch->sym) 1174 if(ch->sym)
1155 name = ch->sym->name; 1175 name = ch->sym->name;
1156 else 1176 else
1157 name = "function pointer"; 1177 name = "function pointer";
1158 1178
1159 if(ch->up == nil) { 1179 if(ch->up == nil) {
1160 // top of chain. ch->sym != nil. 1180 // top of chain. ch->sym != nil.
1161 » » if(ctxt->arch->textflag(ch->sym->text) & NOSPLIT) 1181 » » if(ch->sym->nosplit)
1162 print("\t%d\tassumed on entry to %s\n", ch->limit, name) ; 1182 print("\t%d\tassumed on entry to %s\n", ch->limit, name) ;
1163 else 1183 else
1164 print("\t%d\tguaranteed after split check in %s\n", ch-> limit, name); 1184 print("\t%d\tguaranteed after split check in %s\n", ch-> limit, name);
1165 } else { 1185 } else {
1166 stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize); 1186 stkprint(ch->up, ch->limit + (!HasLinkRegister)*PtrSize);
1167 if(!HasLinkRegister) 1187 if(!HasLinkRegister)
1168 print("\t%d\ton entry to %s\n", ch->limit, name); 1188 print("\t%d\ton entry to %s\n", ch->limit, name);
1169 } 1189 }
1170 if(ch->limit != limit) 1190 if(ch->limit != limit)
1171 print("\t%d\tafter %s uses %d\n", limit, name, ch->limit - limit ); 1191 print("\t%d\tafter %s uses %d\n", limit, name, ch->limit - limit );
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1484 vseprint(buf, buf+sizeof(buf), fmt, arg); 1504 vseprint(buf, buf+sizeof(buf), fmt, arg);
1485 va_end(arg); 1505 va_end(arg);
1486 print("%s%s%s\n", tn, sep, buf); 1506 print("%s%s%s\n", tn, sep, buf);
1487 1507
1488 nerrors++; 1508 nerrors++;
1489 if(nerrors > 20) { 1509 if(nerrors > 20) {
1490 print("too many errors\n"); 1510 print("too many errors\n");
1491 errorexit(); 1511 errorexit();
1492 } 1512 }
1493 } 1513 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b