-
Notifications
You must be signed in to change notification settings - Fork 0
/
2008-05.html
989 lines (754 loc) · 57.6 KB
/
2008-05.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
<!DOCTYPE html>
<html lang="en-us" dir="ltr" itemscope itemtype="http://schema.org/Article">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Blogue do Caloni</title>
<meta name="author" content="Caloni" />
<meta name="generator" content="txt2blog 0.0.1">
<meta property="og:title" content="Blogue do Caloni"/>
<meta property="og:type" content="website"/>
<meta property="og:url" content="http://www.caloni.com.br"/>
<meta property="og:image" content="/img/about-brand.png"/>
<meta property="og:description" content="Write for computers, people and food."/>
<link href="/index.xml" rel="feed" type="application/rss+xml" title="Blogue do Caloni"/>
<link rel="stylesheet" type="text/css" href="/css/custom.css"/>
<link rel="stylesheet" type="text/css" href="/css/jquery-ui.css"/>
<script src="/js/jquery-1.12.4.js"></script>
<script src="/js/jquery-ui.js"></script>
<script src="/js/copy_clipboard.js"></script>
<script>
var quick_search_posts = [
];
</script>
<script src="/js/quick_search.js"></script>
<script src="/js/list.js"></script>
<link rel="icon" href="/img/favicon.ico"/>
</head>
<body style="min-height:100vh;display:flex;flex-direction:column">
<nav class="navbar has-shadow is-white"
role="navigation" aria-label="main navigation">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item" href="months.html">
<div class="is-4"><b>caloni::2008-05</b></div>
</a>
</div>
</div>
</nav>
<div class="container">
<div class="column">
<div style="min-height:56vh">
<div style="padding-bottom: 1em;"></div>
<ul style="list-style: none;">
<li><small><a href="2008-05.html#acessando_memoria_fisica_no_windbg">Acessando memória física no WinDbg</a></small></li>
<li><small><a href="2008-05.html#read_the_functional_manual">Read The Functional Manual</a></small></li>
<li><small><a href="2008-05.html#como_tratar_um_merge_no_bazaar">Como tratar um merge no Bazaar</a></small></li>
<li><small><a href="2008-05.html#kernel_mode_user_mode">Kernel Mode >> User Mode, ou Como Fazer Debug de User Mode pelo Kernel Mode</a></small></li>
<li><small><a href="2008-05.html#aquele_do_while_engracado">Aquele do-while engraçado</a></small></li>
<li><small><a href="2008-05.html#busca_do_google_com_atalhos">Busca do Google com atalhos</a></small></li>
<li><small><a href="2008-05.html#mousetool_clique_automatico_do_seu_rato">MouseTool: clique automático do seu rato</a></small></li>
<li><small><a href="2008-05.html#aprendendo_rapidamente_conceitos_essenciais_do_windbg">Aprendendo rapidamente conceitos essenciais do WinDbg</a></small></li>
<li><small><a href="2008-05.html#how_to_run_anything_as_a_service">How to run anything as a service</a></small></li>
<li><small><a href="2008-05.html#como_criar_uma_lib_no_visual_studio">Como criar uma LIB no Visual Studio</a></small></li>
</ul>
<span id="acessando_memoria_fisica_no_windbg" title="Acessando memória física no WinDbg"/></span>
<section id="section_acessando_memoria_fisica_no_windbg">
<p class="title"><a href="2008-05.html#acessando_memoria_fisica_no_windbg">#</a> Acessando memória física no WinDbg</p>
<span class="title-heading">Caloni, 2008-05-01 <a href="coding.html">coding</a><a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_acessando_memoria_fisica_no_windbg')"><sup>[copy]</sup></a></span>
<p>Como muitos devem saber, acessar memória virtual no WinDbg é coisa de criança, assim como em todo depurador decente. Se estamos falando de kernel mode então, nem se fala! A memória virtual é parte integrante do sistema operacional. Podemos saber mais sobre isso na apresentação do Strauss sobre <a href="http://www.1bit.com.br/downloads/por_dentro_do_windows_memoria.pdf">gerenciamento de memória no Windows</a>.</p>
<p>Porém, existem situações, como a que passei essa semana, onde é preciso saber e alterar o conteúdo da memória de verdade, mesmo. Quando eu falo "de verdade mesmo" estou falando em acessar a memória através do seu endereçamento real, que conta do zero até o final da sua memória RAM, sem divisão de processos e sem proteções de acesso.</p>
<p>Para isso é que serve um depurador de verdade, mesmo.</p>
<p>No modo real, onde vivem sistemas como o MS-DOS e programas como o Turbo C, a memória é acessada através do par de coordenadas conhecido como segmento e offset. Entre outros motivos, isso acontece porque em um determinado momento da história o 8086 possuía 16 bits em seus registradores, mas conseguia endereçar até 640 quilobytes, o que resulta em 640 vezes 1024, ou seja, 655366 bytes, um número dez vezes maior do que 65536 mil, ou 2 elevado a 16, o maior número representado por 16 bits.</p>
<p>Dessa forma, foi necessário o uso de mais 4 bits para fazer a coisa funcionar, pois como podemos notar logo abaixo, a representação do último byte de 640 KB exige isso:</p>
<pre>
10 16 16 16 16 dec
A 0 0 0 0 hex
1010 0000 0000 0000 0000 bin
</pre>
<p>Para conseguir esses 4 bits adicionais foram usados dois registradores em conjunto, o segmento e o offset. Funciona assim: o segmento é multiplicado por 16 (ou deslocado 4 bits à esquerda) e logo depois é somado com o offset, resultando no endereçamento desejado:</p>
<pre>
segment: 0x 9022
offset: 0x 1514
0x 9022
0x 1514 (+)
real addr: 0x 91734
</pre>
<p>Ou seja, para acessar o byte de número 595764, ou 0x91734 podemos usar o segmento 0x9022 com o offset 0x1514. A soma desses dois com o segmento deslocado irá resultado no endereço flag, ou seja, aquele que obtemos se contarmos a memória do zero até o final da RAM. Importante lembrar que na época a RAM não costumava ser de valores como 2GB ou até 4GB, mas em KB mesmo. Isso explica a limitação do 8086 em endereçar até 640 KB.</p>
<p>Se nós repararmos bem, veremos que esse método implica em conseguirmos acessar o mesmo byte com um conjunto de segmentos e offsets diferentes, já que a soma pode ser resultado de operandos diversos. Esse é o chamado efeito de overlapping da memória segmentada, onde os programadores em assembly daquela época tinham que tomar alguns cuidados básicos para não atravessar a memória dos outros. No nosso exemplo acima, por exemplo, seria bem mais fácil chamar nosso bytezinho de segmento 0x9000, offset 0x1734.</p>
<pre>
0x 9000
0x 1734 (+)
0x 91734
</pre>
<p>É verdade! Então, o WinDbg possui alguns comandos extendidos e formas de representar essa memória real, atualmente limitada não mais em 640 KB, mas até onde seus pentes de RAM agüentarem. Os mais comuns são os que imitam os nossos conhecidos dumps de memória: db, dc, dd... Temos daí as extensões !db, !dc, !dd... (note a exclamação do início).</p>
<pre>
windbg -kl
lkd> !db 91734
# 91734 00 (...) .....
# 91744 00 (...) .....
# 91754 00 (...) .....
# 91764 00 (...) .....
# 91774 00 (...) .....
# 91784 00 (...) .....
# 91794 00 (...) .....
</pre>
<p>Simples, assim. O sinal de # no início do dump de memória denota memória real.</p>
<p>Infelizmente, o WinDbg não nos permite ler certas regiões da memória por conta do cacheamento feito pelo processador. Para permitir a leitura em todas as condições, existem três flags que podem ser utilizados:</p>
<ul><li>c lê da memória cacheada</li>
<li>uc lê da memória não-cacheada</li>
<li>wc lê da memória de escrita combinada</li>
</ul>
<p>Nesse caso é possível, embora fique por sua conta e risco, ler qualquer memória não-cacheada usando-se a flag uc.</p>
<p>É possível fazer mais brincadeiras usando os comandos comuns do WinDbg e uma notação diferente da memória. No entanto, é preciso tomar alguns cuidados quando mexer com isso. É recomendado o uso de uma máquina-vítima para esses testes, e não depuração local como estou fazendo.</p>
<pre>
descrição example
------------ ----------
% 32, 64 bits %6400000
& real 8086 &9000:1734
# real 8086 #4C
</pre>
<p>É isso aí. Não espero que você use muitas vezes essa forma de acessar memória. Só que eu usei e... nunca se sabe =)</p>
</section><hr/>
<span id="read_the_functional_manual" title="Read The Functional Manual"/></span>
<section id="section_read_the_functional_manual">
<p class="title"><a href="2008-05.html#read_the_functional_manual">#</a> Read The Functional Manual</p>
<span class="title-heading">Caloni, 2008-05-07<a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_read_the_functional_manual')"><sup>[copy]</sup></a></span>
<p>Percebi essa semana que talvez boa parte da população informática que não progride em suas habilidades, mas gostaria muito, pode ser impedida pela falta de hábito em ler a ajuda do programa | da linguagem | do sistema com calma para encontrar o que procura. Independente do que você é, e para onde quer chegar, saiba que nem tudo na vida pode ser perguntado ao seu colega de baia. Senão você não evolui!</p>
<p>Se você quer dominar um assunto, ou aprender sobre ele, saiba que existem estágio nesse processo. O primeiro estágio é formado principalmente por livros. Se você quer aprender algo, e tem livros sobre o assunto, você é um cara sortudo e feliz.</p>
<p>Eu concordo com <a href="http://www.1bit.com.br">o cara do 1bit</a> quando ele diz que livros são MUITO importantes. Provavelmente eu não seria metade do programador que me considero hoje se só tivesse a experiência, mas não a base fundamental necessária para realmente progredir no que se gosta.</p>
<p>Para algumas coisas pode não existir um livro bem estruturado e organizado nos moldes de "pra iniciante". Nesse caso, na maioria das vezes existe pelo menos o chamado tutorial, ou guia do usuário, que dá o pontapé inicial na cabeça do cara que quer começar a mexer com algum negócio novo.</p>
<p>Outra coisa que acredito que seja fundamental, o segundo nível depois que você começou a ler um bom livro, é saber usar o que você precisa. E para saber usar nada melhor do que ler o manual. Óbvio, não? Pois é, eu também achava... até quando vi um amigo meu tentando descobrir por que as coisas não estavam funcionando, baseado na boa e velha tentativa e erro. É um outro caminho válido, concordo. Mas, se você ainda não deu uma olhada na parte da documentação que fala sobre o problema que você está tendo, então está andando em círculos. E vai aprender bem menos do que poderia.</p>
<p>Outra coisa que ouço com bastante freqüência é a pessoa desanimar por ter muita coisa pra estudar. Bem, se não houvesse tanta coisa assim para estudar não valeria a pena. E nem existiria documentação a respeito. Pra quê, se dá pra decorar tudo de uma vez?</p>
<p>O fato é que os sistemas tendem a ficar cada vez mais complexos e volumosos. Quem duvida, veja o monstro que essas linguagens de alto nível estão se tornando, com mil e uma possibilidades de fazer a mesma coisa.</p>
<p>E como sobreviveríamos nós, meros programadores de fundo de quintal, se não fosse a bênção de uma documentação completa e bem estruturada? Difícil dizer... eu praticamente não vivo sem ler a ajuda de qualquer coisa que eu precise fazer funcionar. Mesmo sendo um programa qualquer que abre um arquivo, coisa que já fiz três milhões de vezes e meia, continuo olhando na ajuda do CreateFile.aspx). E não sou um chimpanzé autista. Eu simplesmente prefiro guardar coisas mais importantes na cabeça do que quantos parâmetros eu preciso passar em uma determinada função. (no caso do CreateFile, são sete!)</p>
<p>Porém, existem aqueles problemas que realmente desafiam o bom senso, a ponto de nem livros, nem tutoriais e muito menos a documentação ter alguma coisa a respeito. O que fazer numa hora dessas? Se você já é um programador tarimbado já sabe do que eu vou falar antes de terminar a primeira linha desse parágrafo: google!</p>
<p>Atualmente existem diversas formas do google te ajudar a encontrar o que você precisa: blogues que falam a respeito (pessoas ajudando pessoas indiretamente), fóruns de discussão sobre o assunto (mais uma vez), páginas do "fabricante" que explicam em melhores detalhes algum problema que está se tornando comum, etc.</p>
<p>É assim que você irá começar a pedir ajuda das pessoas: indiretamente. Não se pergunta nada que já tenha sido respondido. Porque é uma perda de tempo dos dois lados. Do lado que pergunta porque sua resposta já pode estar prontinha em algum canto da web. Do lado que responde porque a pessoa terá que achar o lugar onde respondeu a mesma pergunta, copiar e colar (ou simplesmente ignorar, o que te fará perder mais tempo).</p>
<p>Você já devia saber disso. Faz parte da netiqueta, o guia mundial de bom uso da internet. O quê? Você nunca leu a netiqueta? Se nunca, então comece por lá. Depois venha fazer perguntas interessantes.</p>
<p>Tudo bem, você não conseguiu achar nenhum livro a respeito, não existe tutorial no mundo que resolva o seu problema, e todas as pessoas que possuem a resposta falam e escrevem em mandarim, ou algum outro idioma baseado em pegadas de passarinhos (o google ainda não traduz isso ainda muito bem). Nesse último caso, você ainda tem duas escolhas, sendo a mais fácil delas perguntar para quem entende.</p>
<p>Eu já fiz isso muitas vezes, antes de aprender a me virar (quase) sozinho. Todas que fiz foi por um de dois motivos: intercomunicação ou desespero.</p>
<p>Intercomunicação é quando você fica empolgado com o assunto, conversa com todo mundo que usa o treco que você está aprendendo e anseia por aprender cada vez mais todo dia. Nesse caso a conversa pode ser muito frutífera e animar mais ainda o aprendizado. Porém, é necessário tomar algumas precauções para se certificar que você não está afogando as pessoas de perguntas.</p>
<p>Desespero é quando tudo que você tentou não funciona e você sabe que para adquirir o conhecimento que precisa irá levar muito mais tempo do que fazer a pergunta certa para a pessoa certa. Nesse caso, estou falando realmente de MUITO tempo, coisa de meses a anos.</p>
<p>Também existe um outro caso de desespero, que é quando você sabe que vai perder o emprego se não resolver o problema.</p>
<p>Eu disse que existem duas escolhas nesse estágio. A primeira é perguntar para quem entende do assunto. Porém, o que acontece se você é uma das pessoas que mais entende do assunto que você conhece?</p>
<p>Aí o jeito é resolver sozinho. E, se possível, publicar em algum lugar a solução. A rede agradece.</p>
</section><hr/>
<span id="como_tratar_um_merge_no_bazaar" title="Como tratar um merge no Bazaar"/></span>
<section id="section_como_tratar_um_merge_no_bazaar">
<p class="title"><a href="2008-05.html#como_tratar_um_merge_no_bazaar">#</a> Como tratar um merge no Bazaar</p>
<span class="title-heading">Caloni, 2008-05-09 <a href="coding.html">coding</a><a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_como_tratar_um_merge_no_bazaar')"><sup>[copy]</sup></a></span>
<p>Hoje fizemos um merge de duas versões que entraram em conflito em nosso projeto-piloto usando bzr. Isso geralmente ocorre quando alguma coisa mudou no mesmo arquivo em lugares muito próximos um do outro. Veremos um exemplo de código para ter uma idéia de quão fácil é o processo:</p>
<pre>
#include <stdio.h>
void InitFunction()
{
printf("InitFunction");
}
void DoAnotherJob()
{
char buf[100] = "";
fgets(buf, sizeof(buf), stdin);
printf("New line: %s", buf);
}
void TerminateFunction()
{
printf("TerminateFunction");
}
int main()
{
InitFunction();
while( ! feof(stdin) )
{
DoAnotherJob();
}
TerminateFunction();
}
</pre>
<p>A execução do programa contém uma saída parecida com as linhas abaixo:</p>
<pre>
C:\Tests\bzrpilot>bzppilot.exe
InitFunctionuma linha
New line: uma linha
duas linhas
New line: duas linhas
tres linhas
New line: tres linhas
^Z
New line: TerminateFunction
C:\Tests\bzrpilot>
</pre>
<p>Parece que está faltando algumas quebras de linha. Além de que sabemos que nossos arquivos de entrada poderão conter até 200 caracteres por linha, o que pode gerar um desastre em nosso buffer de 100 bytes. Buffer overflow!</p>
<p>Para corrigir ambos os problemas foram criados dois branches, seguindo as melhores práticas de uso de um controle de fonte distribuído:</p>
<pre>
C:\Tests>bzr branch bzrpilot bzrpilot-linebreak
Branched 1 revision(s).
C:\Tests>bzr branch bzrpilot bzrpilot-bufferoverflow
Branched 1 revision(s).
</pre>
<p>Feitas as correções devidas, o branch linebreak fica com a seguinte cara:</p>
<pre>
void InitFunction()
{
printf("InitFunction\n");
}
void DoAnotherJob()
{
char buf[100] = "";
fgets(buf, sizeof(buf), stdin);
printf("New line: %s\n", buf);
}
void TerminateFunction()
{
printf("TerminateFunction\n");
}
</pre>
<p>Em vermelho podemos notar as linhas alteradas. Uma mudança diferente foi feita para o bug do buffer overflow, em seu branch correspondente:</p>
<pre>
void DoAnotherJob()
{
char buf[200] = "";
fgets(buf, sizeof(buf), stdin);
printf("New line: %s", buf);
}
</pre>
<p>Agora só temos que juntar ambas as mudanças no branch principal.</p>
<blockquote>"Mas espere aí! Não é uma boa termos números mágicos no código!"</blockquote>
<p>Com toda razão, pensa o programador que está corrigindo o bug da quebra de linha, olhando sorrateiramente a função do meio, intocada, DoAnotherJob.</p>
<p>Então ele resolve fazer um pequeno fix "de brinde", desconhecendo que mais alguém andou alterando essas linhas:</p>
<pre>
#define ENOUGH_BYTES 100
void InitFunction()
{
printf("InitFunction\n");
}
void DoAnotherJob()
{
char buf[ENOUGH_BYTES] = "";
fgets(buf, sizeof(buf), stdin);
printf("New line: %s\n", buf);
}
</pre>
<p>Pronto. Um fonte politicamente correto! E que vai causar um conflito ao juntar essa galera. Vamos ver na seqüência:</p>
<pre>
C:\Tests>bzr log bzrpilot-linebreak --short
3 Wanderley Caloni 2008-05-08
A little fix
</pre>
<p> </p>
<pre>
2 Wanderley Caloni 2008-05-08
Corrected line breaks
</pre>
<p> </p>
<pre>
1 Wanderley Caloni 2008-05-08
Our first version
C:\Tests>bzr log bzrpilot-bufferoverflow --short
2 Wanderley Caloni 2008-05-08
Corrigido buffer overflow
</pre>
<p> </p>
<pre>
1 Wanderley Caloni 2008-05-08
Our first version
C:\Tests>bzr log bzrpilot --short
1 Wanderley Caloni 2008-05-08
Our first version
C:\Tests>cd bzrpilot
C:\Tests\bzrpilot>bzr pull ..\bzrpilot-linebreak
M bzppilot.cpp
All changes applied successfully.
Now on revision 3.
C:\Tests\bzrpilot>bzr pull ..\bzrpilot-bufferoverflow
bzr: ERROR: These branches have diverged. Use the merge command to reconcile them.
</pre>
<p>Ops. Algo deu errado no segundo pull. O Bazaar nos diz que os ranches estão diferentes, e que termos que usar o comando merge no lugar.</p>
<pre>
C:\Tests\bzrpilot>bzr merge ..\bzrpilot-bufferoverflow
M bzppilot.cpp
Text conflict in bzppilot.cpp
1 conflicts encountered.
</pre>
<p>Usamos merge no lugar do pull e ganhamos agora um conflito no arquivo bzppilot.cpp, nosso único arquivo. Vamos ver a bagunça que fizemos?</p>
<p>A última coisa que um controle de fonte quer fazer é confundir ou chatear o usuário. Por isso mesmo, a maioria dos conflitos que o Bazaar encontrar nos fontes serão resolvidos usando o algoritmo "se só um mexeu, então coloca a mudança". A tabela do <a href="http://doc.bazaar-vcs.org/bzr.dev/en/user-guide/#merging-changes">guia do usuário</a> ilustra esse algoritmo em possibilidades:</p>
<pre>
| ancestor | first_branch | second_branch | result | comment |
| -------- | ------------ | ------------- | ------- | ---------------- |
| x | x | x | x | não muda |
| x | x | y | y | usuário 2 ganhou |
| x | y | x | y | usuário 1 ganhou |
| x | y | z | ? | conflito!!! |
</pre>
<p>O ancestral é a última modificação em comum dos dois branches que estamos fazendo merge. Do ancestral pra frente cada um seguiu seu caminho, podendo existir quantas modificações quisermos.</p>
<p>Como podemos ver, o conflito só ocorre se ambos os usuário mexerem na mesma parte do código ao mesmo tempo. Eu disse na mesma parte do código, e não apenas no mesmo arquivo. Isso porque se a mudança for feita no mesmo arquivo, porém em locais diferentes, o conflito é resolvido automaticamente.</p>
<p>Em todos os conflitos de texto desse tipo, o Bazaar cria três arquivos de suporte e modifica o arquivo em conflito. Isso para cada conflito.</p>
<ul><li>arquivo.cpp - Resultado de até onde o Bazaar conseguiu o merge</li>
<li>arquivo.cpp.BASE - Versão ancestral do arquivo</li>
<li>arquivo.cpp.THIS - Nosso arquivo original antes de tentar fazer merge</li>
<li>arquivo.cpp.OTHER - A versão que entrou em conflito com a nossa</li>
</ul>
<p>Podemos fazer o merge da maneira que quisermos. Se vamos usar nossa versão de qualquer jeito é só sobrescrever o arquivo.cpp pelo arquivo.cpp.THIS. Se vamos fazer troca-troca de alterações, abrimos os arquivos .THIS e .OTHER e igualamos suas diferenças, copiando-as para arquivo.cpp.</p>
<p>Recomendo primeiramente olhar o que o Bazaar já fez. Se houver dúvidas sobre a integridade das mudanças, comparar diretamente os arquivos THIS e OTHER.</p>
<p>Vamos dar uma olhada na versão criada pelo Bazaar:</p>
<pre>
#include <stdio.h>
#define ENOUGH_BYTES 100
void InitFunction()
{
printf("InitFunction\n");
}
void DoAnotherJob()
{
<<<<<<< TREE
char buf[ENOUGH_BYTES] = "";
=======
char buf[200] = "";
>>>>>>> MERGE-SOURCE
fgets(buf, sizeof(buf), stdin);
printf("New line: %s\n", buf);
}
void TerminateFunction()
{
printf("TerminateFunction\n");
}
int main()
{
InitFunction();
while( ! feof(stdin) )
{
DoAnotherJob();
}
TerminateFunction();
}
</pre>
<p>Ora, vemos que ele já fez boa parte do trabalho para nós: as quebras de linha já foram colocadas e o novo define já está lá. Tudo que temos que fazer é trocar o define por 200 e tirar os marcadores, que é a junção das duas mudanças feitas no mesmo local, e que só um ser humano (AFAIK) consegue juntar:</p>
<pre>
#define ENOUGH_BYTES 200
void InitFunction()
{
printf("InitFunction\n");
}
void DoAnotherJob()
{
char buf[ENOUGH_BYTES] = "";
fgets(buf, sizeof(buf), stdin);
printf("New line: %s\n", buf);
}
</pre>
<p>Resolvido o problema, simplesmente esquecemos das versões .BASE, .THIS e .OTHER e falamos pro Bazaar que está tudo certo.</p>
<pre>
C:\Tests\bzrpilot>bzr resolve bzppilot.cpp
</pre>
<p>O controle de fonte apaga automaticamente os arquivos THIS, BASE e OTHER, mantendo o original como a mudança aceita.</p>
<p>Após as correções dos conflitos, temos que fazer um commit que irá ser o filho dos dois branches que estamos juntando.</p>
<pre>
C:\Tests\bzrpilot>bzr commit -m "Tudo certo"
Committing to: C:/Tests/bzrpilot/
modified bzppilot.cpp
Committed revision 4.
C:\Tests\bzrpilot>bzr log
------------------------------------------------------------
revno: 4
committer: Wanderley Caloni <wanderley@caloni.com.br>
branch nick: bzrpilot
timestamp: Thu 2008-05-08 22:09:35 -0300
message:
Tudo certo
------------------------------------------------------------
revno: 1.1.1
committer: Wanderley Caloni <wanderley@caloni.com.br>
branch nick: bzrpilot-bufferoverflow
timestamp: Thu 2008-05-08 21:47:33 -0300
message:
Corrigido buffer overflow
------------------------------------------------------------
revno: 3
committer: Wanderley Caloni <wanderley@caloni.com.br>
branch nick: bzrpilot-linebreak
timestamp: Thu 2008-05-08 21:49:30 -0300
message:
A little fix
------------------------------------------------------------
revno: 2
committer: Wanderley Caloni <wanderley@caloni.com.br>
branch nick: bzrpilot-linebreak
timestamp: Thu 2008-05-08 21:44:23 -0300
message:
Corrected line breaks
------------------------------------------------------------
revno: 1
committer: Wanderley Caloni <wanderley@caloni.com.br>
branch nick: bzrpilot
timestamp: Thu 2008-05-08 21:33:53 -0300
message:
Our first version
</pre>
<p>A versão do branch alternativo é 1.1.1, indicando que ele saiu da revisão número 1, é o primeiro alternativo e foi o único commit. Se houvessem mais modificações neste branch, elas seriam 1.1.2, 1.1.3 e assim por diante. Se mais alguém quisesse juntar alguma modificação da revisão 1 ela seria 1.2.1, 1.3.1, 1.4.1 e assim por diante.</p>
<p>Um erro comum que pode acontecer é supor que o arquivo original está do jeito que deixamos e já usar o comando resolve diretamente. É preciso tomar cuidado, pois se algum conflito é detectado quer dizer que o Bazaar deixou para você alguns marcadores no fonte original, o que quer dizer que ele simplesmente não vai compilar enquanto você não resolver seus problemas.</p>
<p>Enfim, tudo que temos que lembrar durante um merge do Bazaar é ver os conflitos ainda não resolvidos direto no fonte e alterá-los de acordo com o problema. O resto é codificar.</p>
</section><hr/>
<span id="kernel_mode_user_mode" title="Kernel Mode >> User Mode, ou Como Fazer Debug de User Mode pelo Kernel Mode"/></span>
<section id="section_kernel_mode_user_mode">
<p class="title"><a href="2008-05.html#kernel_mode_user_mode">#</a> <a class="external" href="https://youtu.be/j1f7DQkFI5A">Kernel Mode >> User Mode, ou Como Fazer Debug de User Mode pelo Kernel Mode</a></p>
<span class="title-heading">Caloni, 2008-05-13 <a href="coding.html">coding</a> <a href="windbg.html">windbg</a><a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_kernel_mode_user_mode')"><sup>[copy]</sup></a></span>
<p>Existem algumas situações onde um depurador WYSIWYG é artigo de luxo.</p>
<p>Imagine o seguinte: temos um serviço que inicia automagicamente antes do login do Windows, e possivelmente antes mesmo do ambiente gráfico. Esse serviço tem algum problema que impede que ele funcione sob as circunstâncias de inicialização do sistema. O que fazer? Atachar o WinDbg no processo?</p>
<p>Mas que mané WinDbg? Que mané atachar? Nessa hora nós temos bem menos do que nossos sentidos são capazes de enxergar.</p>
<p>Nessas horas o único que pode nos ajudar é o kernel debugger.</p>
<p>Os depuradores do pacote Debugging Tools (especialmente o ntsd e o cdb) suportam o funcionamento em modo proxy, ou seja, eles apenas redirecionam a saída e os comandos entre as duas pontas da depuração (o depurador e o depurado). Isso é comumente usado em <a href="2008-03.html#windbg_a_distancia">depuração remota</a> e <a href="http://www.driverentry.com.br">depuração de kernel</a>, quando o sistema inteiro está congelado. O objetivo aqui é conseguir os dois: depurar remotamente um processo em um sistema que está travado.</p>
<p>Para isso podemos nos utilizar do parâmetro -d, que manda o depurador redirecionar toda saída e controle para o depurador de kernel. Para que isso funcione o depurador já deve estar atachado no sistema-alvo. A coisa funciona mais ou menos assim:</p>
<img src="img/kernel_mode_user_mode_windbg_user_kernel.png"/>
<p>Com essa configuração temos a vantagem de ter o sistema congelado só pra nós, ao mesmo tempo que conseguimos depurar nosso processo fujão, passo-a-passo.</p>
<p>A única desvantagem é não ter uma GUI tão poderosa quando o "WinDbg fonte colorido, tooltips, etc". Pra quem não liga pra essas frescuras, é possível depurar processos de maneira produtiva utilizando esse cenário.</p>
<p>Para ativar qualquer programa que irá rodar nesse modo, basta usar o aplicativo gflags:</p>
<pre>
gflags /p /enable servico.exe /debug "c:\path\ntsd.exe -d"
</pre>
<p>Para entender o fluxo de navegação pelo mundo kernel-user misturados é preciso dar uma lida bem profunda na ajuda do Debugging Tools para entender como as coisas estão funcionando nessa configuração milagrosa que estamos usando. Procure por "Controlling the User-Mode Debugger from the Kernel Debugger". Também é possível ouvir falar parcamente sobre isso no livro Advanced Windows Debugging na parte "Redirecting a User Mode Debugger Through a Kernel". A vantagem é que vem de brinde uma bela figura para pendurar em um quadro no escritório (embora eu possa jurar que já vi essa figura na ajuda do WinDbg):</p>
<img src="img/kernel_mode_user_mode_windbg_user_kernel2.png"/>
<p>Como podemos notar, o controlador de tudo é o kernel debugger. Assim que o depurador de processo entra em ação, ele se comunica com o depurador de kernel que entra no modo user mode prompt, pedindo entrada para ser redirecionada ao depurador de processo. Existem alguns caminhos para sair de um estado e entrar em outro, como o comando .breakin e o .sleep.</p>
<p>É necessário recomentar: estamos nos comunicando com um depurador e o seu processo depurado em um sistema totalmente travado. Isso quer dizer que o acesso a coisas como código-fonte e símbolos é extremamente limitado, porém não impossível. Apenas mantenha-os localmente na máquina-vítima, pois uma comunicação pela rede não irá funcionar.</p>
<p>A depuração com a linha atual no código-fonte demarcando onde estamos também não é possível, uma vez que o WinDbg da ponta de cá apenas faz o papel de garoto de recados para o "depurador de verdade" do outro lado (no nosso exemplo, o ntsd). Isso quer dizer que a forma mais "fácil" de ir passo-a-passo é usar o comando p (step) ou t (trace), além de habilitar o uso de fonte em 100%.</p>
<pre>
input> .srcpath c:\maquina-vitima\src
input> l+* $$ habilita uso de código-fonte no ntsd
...
0:000> p
> 15: int main() $$ número da linha seguido do fonte
> 16: {
0:000> bp myFunction
0:000> g
0:000>
</pre>
<p>Um tipo de problema que só pode ser depurado dessa maneira enfatiza a importância do uso de unit tests, além de um controle de qualidade mais aguçado antes de liberar uma versão para o cliente.</p>
</section><hr/>
<span id="aquele_do_while_engracado" title="Aquele do-while engraçado"/></span>
<section id="section_aquele_do_while_engracado">
<p class="title"><a href="2008-05.html#aquele_do_while_engracado">#</a> Aquele do-while engraçado</p>
<span class="title-heading">Caloni, 2008-05-15 <a href="coding.html">coding</a> <a href="ccpp.html">ccpp</a><a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_aquele_do_while_engracado')"><sup>[copy]</sup></a></span>
<p>Nesses últimos dias andei conversando com um amigo que está estudando sistemas operacionais na faculdade. Melhor ainda, vendo o código real de um sistema operacional em funcionamento. A conseqüência é que, além de aprender um bocado de como as coisas funcionam de verdade debaixo dos panos, acaba-se aprendendo alguns truquezinhos básicos e tradicionais da linguagem C.</p>
<p>Por exemplo, é um hábito conhecido o uso de construções do-while quando existe a necessidade de definir uma macro que possui mais de um comando em vez de usar a igualmente conhecida { construção de múltiplos comandos entre chaves }.</p>
<p>O que talvez não seja tão conhecido é o porquê das coisas serem assim.</p>
<p>Vamos imaginar uma macro de logue que é habilitada em compilações debug, mas é mantida em silêncio em compilações release:</p>
<pre>
#ifdef NDEBUG
#define MYTRACE(message) /*nada*/
#else
#define MYTRACE(message) \
{ \
char buffer[500]; \
sprintf(buffer, \
"DBG: %s(%d) %s\n", \
__FILE__, \
__LINE__, \
message); \
output(buffer); \
}
#endif /* NDEBUG */
</pre>
<p>Nada de mais, e parece até funcionar. Porém, como veremos nas próximas linhas, esse é realmente um exemplo de código "buguento", já que uma chamada dentro de uma construção if-else simplesmente não funciona.</p>
<pre>
if( exploded() )
MYTRACE("Oh, my God");
else
MYTRACE("That's right");
error C2181: illegal else without matching if
</pre>
<p>Por que isso? Para responder a essa questão nós precisamos olhar um pouco mais de perto no resultado do preprocessador da linguagem, que apenas troca nossa macro pelo pedaço de código que ela representa:</p>
<pre>
if( exploded() )
{
char buffer[500];
sprintf(buffer,
"DBG: %s(%d) %s\n",
__FILE__,
__LINE__,
"Oh, my God");
output(buffer);
};
else
{
char buffer[500];
sprintf(buffer,
"DBG: %s(%d) %s\n",
__FILE__,
__LINE__,
"That's right");
output(buffer);
};
</pre>
<p>Dessa forma, podemos ver o porquê. Quando chamamos a macro, geralmente usamos a sintaxe de chamada de função, colocando um sinal de ponto-e-vírgula logo após a chamada. Essa é a maneira correta de se chamar uma função, mas no caso de uma macro, dessa macro, é um desastre, porque ela cria dois comandos em vez de um só (um ponto-e-vírgula vazio, apesar de não fazer nada, é um comando válido). Então, isso é o que o compilador faz:</p>
<pre>
if( instruction )
{
/* um monte de comandos */
} /* aqui eu esperaria um else ou uma instrução nova */
; /* uma instrução nova! ok, sem else desa vez */
else /* espere ae! o que esse else está fazendo aqui sem um if?!?! */
{
/* mais comandos */
}
</pre>
<p>Pense sobre o comando vazio como se ele fosse um comando real, o que é a maneira mais fácil de entender o erro de compilação que recebemos ao compilar o código abaixo:</p>
<pre>
if( error() )
{
printf("error");
}
printf("here we go");
else /* llegal else without matching if! */
{
printf("okay");
}
</pre>
<p>Por essa razão, a maneira tradicional de escapar desse erro comum é usar uma construção válida que peça de fato um ponto-e-vírgula no final. Felizmente nós, programadores C/C++, temos essa construção, e ela é... muito bem, o do-while!</p>
<pre>
do
{
/* múltiplos comandos aqui */
}
while( expression )
; /* eu espero um ponto-e-vírgula aqui,
para finalizar minha
instrução do-while */
</pre>
<p>Assim nós podemos reescrever nossa macro de logue da maneira certa (e todas as 549.797 macros já escritas em nossa vida de programador). E, apesar de ser uma construção um tanto bizarra, ela funciona melhor do que nossa tentativa inicial:</p>
<pre>
#ifdef NDEBUG
#define MYTRACE(message) /*nada*/
#else
#define MYTRACE(message) \
do \
{ \
char buffer[500]; \
sprintf(buffer, \
"DBG: %s(%d) %s\n", \
__FILE__, \
__LINE__, \
message); \
output(buffer); \
} \
while( 0 )
#endif /* NDEBUG */
</pre>
<p>Ao usar um do-while (com uma expressão que retorna falso dentro do teste, de maneira que o código seja executado apenas uma vez) a construção if-else consegue funcionar perfeitamente:</p>
<pre>
if( exploded() )
do
{
char buffer[500];
sprintf(buffer,
"MYTRACE: %s(%d) %s\n",
__FILE__,
__LINE__,
"Oh, my God");
OutputDebugString(buffer);
}
while( 0 );
else
do
{
char buffer[500];
sprintf(buffer,
"MYTRACE: %s(%d) %s\n",
__FILE__,
__LINE__,
"That's right");
OutputDebugString(buffer);
}
while( 0 );
</pre>
</section><hr/>
<span id="busca_do_google_com_atalhos" title="Busca do Google com atalhos"/></span>
<section id="section_busca_do_google_com_atalhos">
<p class="title"><a href="2008-05.html#busca_do_google_com_atalhos">#</a> Busca do Google com atalhos</p>
<span class="title-heading">Caloni, 2008-05-19<a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_busca_do_google_com_atalhos')"><sup>[copy]</sup></a></span>
<p>Eu adoro atalhos de teclado. Desde meus primeiros anos usando computadores, atalhos têm se tornado minha obsessão. Sempre faço minha pesquisa pessoal de tempos em tempos, colecionando e usando novos atalhos descobertos. Por um bom tempo eu evitei ter que usar o mouse, treinando-me para lembrar de todas as seqüências de teclas que conhecia.</p>
<p>Eu não tenho nada contra o uso do mouse nem as pessoas que o usam. Eu apenas não sou tão entusiástico em usar o mouse. Por algum tempo, eu até acreditei que o ponteiro do cursor estava me atrapalhando, então eu desenvolvi um programa para tirá-lo da tela (usando um atalho de teclado, claro). Porém, mais uma vez, não sou contra seu uso. Eu mesmo uso-o de vez em quando (quando eu preciso).</p>
<p>Até algum tempo atrás a web não era muito convidativa para usuários de atalhos. Então surgiu o Google e as suas aplicações que suportavam essa característica, o que me deu uma razão a mais para passar a usar seu cliente de e-mail e leitor de notícias sem pressionar constantemente a tecla Tab. No entanto, ainda faltava a mesma funcionalidade para seu buscador. Felizmente, isso não é mais verdade.</p>
<p>Ainda em teste, eu comecei a usar os novos atalhos de teclado na busca do Google disponíveis no saite Google Experimental Search. Até agora existem atalhos para próximo resultado (J), resultado anterior (K), abertura da busca (O ou Enter) e colocação do cursor na caixa de busca (/). Eles funcionam exatamente como o Gmail e o Google Reader. Eu fiquei tão empolgado com a idéia que mudei o complemento de busca do Google de dentro do meu Firefox. E agora vou contar como isso pode ser feito facilmente (nota: minhas dicas servem para usuário de Windows apenas).</p>
<p>Provavelmente seu complemento de busca estará em uma das duas pastas abaixo:</p>
<pre>
%programfiles%\Mozilla Firefox\searchplugins
%appdata%\Mozilla\Firefox\Profiles\*.default\searchplugins
</pre>
<p>O arquivo do complemento tem o nome google.xml e você pode editá-lo usando o Bloco de Notas ou qualquer outro editor de texto simples (sem formatação). Abaixo está o ponto onde você deve inserir a nova linha que irá ativar os atalhos dentro da página de buscas do Google.</p>
<pre>
<Url type="text/html" method="GET" template="http://www.google.com/search">
<Param name="q" value="{searchTerms}"/>
<...>
<Param name="esrch" value="BetaShortcuts"/> <!-- Google Shortcuts Here -->
<!-- Dynamic parameters -->
<...>
</Url>
</pre>
<p>É isso aí. Agora você pode ter o melhor dos dois mundos: o melhor buscador da internete com atalhos. Existirá maneira de se tornar ainda mais produtivo?</p>
</section><hr/>
<span id="mousetool_clique_automatico_do_seu_rato" title="MouseTool: clique automático do seu rato"/></span>
<section id="section_mousetool_clique_automatico_do_seu_rato">
<p class="title"><a href="2008-05.html#mousetool_clique_automatico_do_seu_rato">#</a> MouseTool: clique automático do seu rato</p>
<span class="title-heading">Caloni, 2008-05-21 <a href="coding.html">coding</a> <a href="projects.html">projects</a><a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_mousetool_clique_automatico_do_seu_rato')"><sup>[copy]</sup></a></span>
<p>Bem, como a maioria de vocês já sabe, eu realmente não gosto de mouses. Apesar disso, respeito os usuário que usam-no e até gostam dele. Essa é a razão por que estou escrevendo mais uma vez sobre isso. Dessa vez, irei mostrar um programa que eu uso todos os dias: MouseTool, para os usuários que não usam o mouse, mas gostam dele.</p>
<p>O principal objetivo do programa é evitar de clicar no mouse, simulando um clique toda vez que o usuário pára de mover o ponteiro. E é só isso: simples, eficiente e mouseless =).</p>
<p>Existem algumas outras opções como arrastar-e-soltar e clique-duplo, ambas disponíveis pelo próprio programa através de atalhos do teclado ou mudança de estado, situação onde o usuário antes pousa o ponteiro sobre a ação desejada e depois pousa o ponteiro sobre o alvo, dessa forma alternando entre os três modos.</p>
<p>O MouseTool originalmente foi uma ferramente de fonte aberto. Isso significa que a última versão do código-fonte está disponível, certo? Errado. Na verdade, eu não consegui, por mais que tentasse achar, a versão para baixar do código.</p>
<p>Felizmente meu amigo <a href="http://marcioandreyoliveira.blogspot.com/search/label/GMouseTool">Marcio Andrey</a> já havia baixado o fonte algum tempo atrás e, assim como eu, ele gostaria de torná-lo disponível para todos que gostassem de usá-lo e alterá-lo. Por isso que estou publicando-o aqui. Ele é gratuito e aberto. Façam o que quiserem com ele =).</p>
<p>Vamos aproveitar o código-fonte e mostrar como explorar um código não escrito por nós. Normalmente as primeiras coisas a fazer são: baixar o arquivo compactado e descompactá-lo dentro de uma nova pasta. Dessa forma encontramos o arquivo de projeto (nesse caso, MouseTool.dsw) e tentamos abri-lo. Falhando de início miseravelmente porque acredito que ninguém mais utilize a versão do Visual Studio que abre isso.</p>
<p>Normalmente programadores de projetos de fonte aberto estão acostumados a obter os arquivos-fonte, modificá-los, publicá-los e assim por diante. Porém isso não é quase nunca verdade para programadores Windows de aplicativos estritamente comerciais. É necessário se reajustar à nova cultura para aproveitar os benefícios da política de fonte aberto.</p>
<p>Por exemplo, dados os arquivos-fonte, nós podemos explorar algumas partes interessantes de coisas que gostaríamos de fazer em nossos próprios programas. São trechos pequenos de código que fazem coisas úteis que gastaríamos algumas horas/dias para pesquisar na internet e achar a resposta procurada. Através de um projeto de fonte aberto, conseguimos usar um programa e ao mesmo tempo aprender seu funcionamento. E a principal parte é: nós temos o fonte, mas não os direitos autorais.</p>
<p>PS: MouseTool agora tem uma versão Linux em um projeto no Source Forge! Seu nome é <a href="http://gmousetool.sourceforge.net">GMouseTool</a>, projeto criado por Márcio de Oliveira.</p>
<pre>
</pre>
</section><hr/>
<span id="aprendendo_rapidamente_conceitos_essenciais_do_windbg" title="Aprendendo rapidamente conceitos essenciais do WinDbg"/></span>
<section id="section_aprendendo_rapidamente_conceitos_essenciais_do_windbg">
<p class="title"><a href="2008-05.html#aprendendo_rapidamente_conceitos_essenciais_do_windbg">#</a> Aprendendo rapidamente conceitos essenciais do WinDbg</p>
<span class="title-heading">Caloni, 2008-05-23 <a href="coding.html">coding</a> <a href="windbg.html">windbg</a><a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_aprendendo_rapidamente_conceitos_essenciais_do_windbg')"><sup>[copy]</sup></a></span>
<p>Todo o poder e flexibilidade do pacote Debugging Tools da Microsoft pode ser ofuscado pela sua complexidade e curva de aprendizagem. Afinal de contas, usar o depurador do Visual Studio é muito fácil, quando se começa a usar, mas mesmo assim conheço muitos programadores que relutam em depurar passo-a-passo, preferindo a depuração por meio de "MessageBoxes" ou saídas na tela. Imagine, então, a dificuldade que não é para quem conseguiu às duras penas aprender a tornar um hábito a primeira passada do código novo em folha através do F10 começar a fazer coisas como configurar símbolos e digitar comandos esdrúxulos em uma tela em modo texto. Para piorar a questão, existem aqueles que defendem o uso unificado de uma ferramenta que faça tudo, como um telefone celular. Eu discordo. Quando a vantagem competitiva de uma ferramenta sobre outra é notável, nada pior que ficar preso em um ambiente legalzinho que faz o mínimo para você, mas não resolve o seu problema de deadlock.</p>
<p>Foi pensando nessa dificuldade que foi escrita uma <a href="http://index-of.es/Windows/WinDBG_A_to_Z_color.pdf">apresentação nota dez</a> por Robert Kuster que explica todas as minúcias importantes para todo programador iniciante e experiente na arte de "WinDbgear". "WinDbg. From A to Z!" é uma ferramenta tão útil quanto o próprio WinDbg, pois explica desde coisas simples que deve-se saber desde o início, como configurar símbolos, quanto assuntos mais avançados, como depuração remota. Até para quem já está no nível avançado vale a pena recapitular algumas coisas que já foram ditas no AWD.</p>
<p>Mesmo tentando ser sucinto, o assunto ocupou um conjunto de 111 transparências que demoram de uma a duas horas de leitura cuidadosa, se você não fizer testes durante o trajeto. Entre as coisas que eu li e reli, segue uma lista importante para nunca ser esquecida (entre parênteses o número das transparências que considero mais importantes):</p>
<ul><li>O que é são as bibliotecas de depuração do Windows e como elas podem te ajudar (6 e 9)</li>
<li>O que são símbolos de depuração (11, 12, 14)</li>
<li>Como funciona a manipulação de exceções e como depurar (18, 19, 85)</li>
<li>Como configurar seu depurador para funcionar globalmente (20)</li>
<li>Tipos de comandos no WinDbg (22)</li>
<li>Configurando símbolos e fontes no WinDbg (24, 25)</li>
<li>Interagindo com as janelas do WinDbg (33)</li>
<li>Informações sobre processos, pilhas e memória (29, 41, 43, 45, 66)</li>
<li>Informações sobre threads e locks (31, 55)</li>
<li>Comandos úteis com strings e memórias (66)</li>
<li>Avaliando expressões no WinDb: MASM e C++ (70, 71)</li>
<li>Usando breakpoints no WinDbg (básico) (81)</li>
<li>Usando breakpoints no WinDbg (complicado) (83, 84)</li>
<li>Depuração remota (muito útil!) (87)</li>
<li>Escolhendo a melhor ferramenta para o problema (fantástico!) (108)</li>
</ul>
<p>Além da enchurrada de informações, o autor ainda explica a teoria com comandos digitados no próprio WinDbg, dando um senso bem mais prático à ferramenta. Ou seja, é útil tanto para os que aprendem por definições abstratas e lista de comandos quanto os que preferem já colocar a mão na massa e massacrar o bom e velho notepad.exe.</p>
<p>No final, duas dicas importantíssimas do autor para quem deseja se aventurar nesse mundo: leia a documentação do WinDbg (que também é ótima, apesar de bem mais extensa) e aprenda assembly (simplesmente essencial para resolver muitos problemas).</p>
<p>Se você ainda não teve tempo de se dedicar à depuração avançada em Windows e pensa que nunca terá, dedique duas horinhas divididas em períodos de 15 minutos por dia para explorar esse fantástico tutorial, que com certeza, se bem aplicado, reduzirá exponencialmente seu tempo de resolução de problemas.</p>
<p>Existe uma <a href="http://windbg.info/doc/2-windbg-a-z.html">tradução para inglês</a> desse texto no saite do próprio Robert Kuster, que usou-o como uma espécie de introdução.</p>
</section><hr/>
<span id="how_to_run_anything_as_a_service" title="How to run anything as a service"/></span>
<section id="section_how_to_run_anything_as_a_service">
<p class="title"><a href="2008-05.html#how_to_run_anything_as_a_service">#</a> How to run anything as a service</p>
<span class="title-heading">Caloni, 2008-05-27 <a href="coding.html">coding</a> <a href="english.html">english</a><a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_how_to_run_anything_as_a_service')"><sup>[copy]</sup></a></span>
<p>The biggest advantage running an application as a service, interactive or not, is to allow its start before a logon be performed. An example that happens to me is the need of debugging a <a href="2007-08.html#gina_x_credential_provider">GINA</a>. In order to do this, I need the Visual Studio remote debugger be started before logon. The easiest and fastest solution is to run Msvcmon, the server part of debugging, as a service.</p>
<p>Today I've figured out a pretty interesting shortcut to achieve it.</p>
<p>An <a href="http://www.alex-ionescu.com/?p=59">Alex Ionescu article</a> talks about this command line application used to create, initiate and remove services. Even not being the article focus, I found the information pretty useful, since I didn't know such app. Soon some ideas starting to born in my mind:</p>
<blockquote>"What if I used this guy to run notepad?"</blockquote>
<p>Well, the Notepad is the default test victim. Soon, the following line would prove possible to run it in the system account:</p>
<pre>
sc create Notepad binpath= "%systemroot%\NOTEPAD.EXE" type= interact type= own
</pre>
<p>However, as every service, it is supposed to communicate with the Windows Service Manager. Since Notepad even "knows" it is now a superpowerful service, the service initialization time is expired and SCM kills the process.</p>
<pre>
>net start notepad
The service is not responding to the control function.
More help is available by typing NET HELPMSG 2186.
</pre>
<p>As would say my friend <a href="http://codebehind.wordpress.com">Thiago</a>, "not good".</p>
<p>"Yet however", SCM doesn't kill the child processes from the service-process. Bug? Feature? Workaround? Whatever it is, it can be used to initiate our beloved msvcmon:</p>
<pre>
set binpath=%systemroot%\system32\cmd.exe /c c:\Tools\msvcmon.exe -tcpip -anyuser -timeout -1
sc create Msvcmon binpath= "%binpath%" type= interact type= own
</pre>
<p>Now, when we start Msvcmon service, the process cmd.exe will be create, that on the other hand will run the msvcmon.exe target process. Cmd in this case will only wait for its imminent death.</p>
<img src="img/how_to_run_anything_as_a_service_msvcmon_service.png"/>
</section><hr/>
<span id="como_criar_uma_lib_no_visual_studio" title="Como criar uma LIB no Visual Studio"/></span>
<section id="section_como_criar_uma_lib_no_visual_studio">
<p class="title"><a href="2008-05.html#como_criar_uma_lib_no_visual_studio">#</a> Como criar uma LIB no Visual Studio</p>
<span class="title-heading">Caloni, 2008-05-29 <a href="coding.html">coding</a><a href="2008-05.html"> <sup>[up]</sup></a> <a href="javascript:;" onclick="copy_clipboard('section#section_como_criar_uma_lib_no_visual_studio')"><sup>[copy]</sup></a></span>
<p>Quando se está começando no ramo, alguns detalhes nunca vêm à tona para o programador novato. Ele simplesmente vai codando até se sentir satisfeito com o prazer que é proporcionado pela prática da arte dos deuses de silício.</p>
<p>Isso, em termos práticos, quer dizer que todo o fonte vai ser escrito no mesmo ".c", que aliás talvez nem se dê ao luxo de possuir seu próprio ".h": pra quê, se as funções são todas amigas de infância e todas se conhecem?</p>
<p>No começo não existe nenhum problema, mesmo. O fonte vai ser pequeno. A coisa só complica quando não dá mais pra se achar no meio de tantos gotos e ifs aninhados. Talvez nessa hora o programador já-não-tão-novato até tenha descoberto que é possível criar vários arquivos-fonte e reuni-los em um negócio chamado projeto, e que existem IDEs, como o Visual Studio, que organizam esses tais projetos.</p>
<p>A partir daí, para chegar em uma LIB, já é meio caminho andado.</p>
<blockquote>"Mas, afinal de contas, pra que eu preciso de uma LIB, mesmo?"</blockquote>
<p>Boa pergunta. Uma LIB, ou biblioteca, nada mais é do que um punhado de ".obj" colocados todos no mesmo arquivo, geralmente um ".lib". Esses ".obj" são o resultado da compilação de seus respectivos ".c" de origem.</p>
<img src="img/como_criar_uma_lib_no_visual_studio_salada2.gif"/>
<p>Alguns acreditam ser esse negócio de LIB uma pura perda de tempo, pois existem trocentas configurações diferentes (e incompatíveis) e trocentas compilações diferentes para gerenciar. Outros acham que o problema está no tempo de compilação, enquanto outros defendem o uso dos ".obj" de maneira separada. Esse artigo não presume que nem um nem outro seja melhor. Apenas ensina o que você precisa saber para criar sua primeira LIB usando o Visual Studio Express.</p>
<p>Vamos lá?</p>
<p>Após abrir o VS, tudo que precisamos fazer é ir em New, Project, e escolher a configuração de "Win32 Project":</p>
<img src="img/como_criar_uma_lib_no_visual_studio_myfirstlib.png"/>
<p>A seguir, escolhemos nas opções do assistente criar uma "Static library", e desmarcamos a opção de "Precompiled header" para evitar má sorte logo no primeiro projeto de LIB (má sorte significa horas procurando erros incríveis que você só irá fazer desaparecer se recompilar tudo com o uso do famigerado "Rebuild All"; espero que isso dê certo para você, para mim não tem funcionado).</p>
<img src="img/como_criar_uma_lib_no_visual_studio_myfirstlib2.png"/>
<p>E pronto! Temos um projeto de LIB completo, funcional e... um tanto inútil. Mas, calma lá. Ainda não terminamos.</p>
<img src="img/como_criar_uma_lib_no_visual_studio_myfirstlib3.png"/>
<p>Conforme o programador consegue se livrar das maldições das mil dependências, aos poucos ele vai conseguindo novas funções genéricas e encaixáveis para colocar em sua coleção de objs. Essa com certeza não é uma tarefa fácil, mas ei, quem disse que esse trampo de programador seria fácil?</p>
<p>Vamos imaginar que você é muito do sem imaginação (típico de pessoas que mantêm blogues) e criou duas funções lindíssimas que somam e multiplicam dois números:</p>
<pre>
int sum(int a, int b)
{
return a + b;
}
int mult(int a, int b)
{
return a * b;
}
</pre>
<p>Não são aquelas coisas, mas são genéricas e, até certo ponto, "úteis" para o nosso exemplo.</p>
<p>Agora, tudo que temos que fazer é criar dois arquivos: mymath.c e mymath.h. No mymath.c, colocamos as funções acima exatamente como estão. No mymath.h, colocamos apenas as declarações dessas duas funções, apenas para avisar outros ".c" que existem duas funções que fazem coisas incríveis nessa nossa LIB.</p>
<pre>
/* soma dois números */
int sum(int a, int b);
/* multiplica dois números */
int mult(int a, int b);
</pre>
<p>Adicionamos esses dois arquivos ao projeto (se já não estão), e voilà!</p>
<pre>
------ Build started: Project: MyFirstLib, Configuration: Debug Win32 ------
Compiling...
mymath.c
Creating library...
Build log was saved at "file://c:\Projects\temp\MyFirstLib\Debug\BuildLog.htm"
MyFirstLib - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
</pre>
<p>Para usar uma LIB temos inúmeras maneiras de fazê-lo. A mais simples que eu conheço é criar um novo projeto no mesmo Solution de sua LIB. Um console, por exemplo:</p>
<img src="img/como_criar_uma_lib_no_visual_studio_myfirstlib4.png"/>
<img src="img/como_criar_uma_lib_no_visual_studio_myfirstlib5.png"/>
<img src="img/como_criar_uma_lib_no_visual_studio_myfirstlib6.png"/>
<p>Se você seguiu todos os passos direitinho, e eu estou assumindo que você já sabia como criar um projeto console, sua saída da compilação talvez seja mais ou menos essa:</p>
<pre>
------ Build started: Project: MyFirstCmd, Configuration: Debug Win32 ------
Compiling...
mycmd.c
Linking...
mycmd.obj : error LNK2019: unresolved external symbol mult referenced in function main
mycmd.obj : error LNK2019: unresolved external symbol sum referenced in function main
c:\Projects\temp\MyFirstLib\Debug\MyFirstCmd.exe : fatal error LNK1120: 2 unresolved externals
Build log was saved at "file://c:\Projects\temp\MyFirstCmd\Debug\BuildLog.htm"
MyFirstCmd - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========
</pre>
<p>Dois erros! Ele não achou os símbolos mult e sum. Mas eles estão logo ali! E agora?</p>
<p>Nada a temer: tudo que temos que fazer é falar para o Solution que o projeto myfirstcmd depende do projeto myfirstlib:</p>
<img src="img/como_criar_uma_lib_no_visual_studio_myfirstlib7.png"/>
<img src="img/como_criar_uma_lib_no_visual_studio_myfirstlib8.png"/>
<pre>
------ Build started: Project: MyFirstCmd, Configuration: Debug Win32 ------
Linking...
Embedding manifest...
Microsoft (R) Windows (R) Resource Compiler Version 6.0.5724.0
Copyright (C) Microsoft Corporation. All rights reserved.
Build log was saved at "file://c:\Projects\temp\MyFirstCmd\Debug\BuildLog.htm"
MyFirstCmd - 0 error(s), 0 warning(s)
========== Build: 1 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
</pre>
<p>Isso resolve o problema de organização e compilação quando temos dezenas de ".c" espalhados pelo projeto. Existem melhores alternativas, mais bem organizadas e estruturadas, inclusive lingüisticamente falando. No entanto, tudo tem sua hora, e só se deve preocupar-se com isso quando sua solução tiver algumas dezenas de ".lib". Até lá!</p>
</section><hr/>
<span style="float: left;">
<a href="2008-04.html">[2008-04]</a>
<a href="2008-06.html">[2008-06]</a>
</span>
</div>
</div>
</section>
<footer class="footer">
<div class="container">
</div>
</footer>
</body>
</html>